ReactJs儿童没有';父状态更改后无法更新
我正在尝试使用ReactJS构建一个动态组件。因此,我有一个产品列表,每次用户想要添加新产品时,他都会单击+按钮。这将创建一个新产品并将其添加到列表中。列表中有一个名为delete all的按钮,用于删除所有产品 要删除所有产品,我在组件创建时使用了产品列表中以“created”初始化的状态,当用户单击delete all时,我将其更改为“deleted”,以使用ComponentWillUpdate回调更新孩子(产品) 下面是一些代码: index.jsReactJs儿童没有';父状态更改后无法更新,reactjs,jsx,Reactjs,Jsx,我正在尝试使用ReactJS构建一个动态组件。因此,我有一个产品列表,每次用户想要添加新产品时,他都会单击+按钮。这将创建一个新产品并将其添加到列表中。列表中有一个名为delete all的按钮,用于删除所有产品 要删除所有产品,我在组件创建时使用了产品列表中以“created”初始化的状态,当用户单击delete all时,我将其更改为“deleted”,以使用ComponentWillUpdate回调更新孩子(产品) 下面是一些代码: index.js render() { retu
render() {
return (
<div className="App">
<h1>Dynamic List</h1>
<ProductList />
<hr />
<h1>Static List</h1>
<ProductListStatic />
</div>
);
}
render(){
返回(
动态列表
静态列表
);
}
Product.js
class Product extends React.Component {
constructor(props) {
super(props);
this.state = {
state: "created"
};
}
componentDidUpdate(prevProps) {
if (
this.props.parentState === "deleted" &&
this.state.state === "created"
) {
this.setState({ state: "deleted" });
}
}
render() {
if (this.state.state !== "deleted") {
return (
<div style={{ margin: "5px" }}>
Product.....
<button onClick={this.props.addNewProduct}>+</button>
</div>
);
} else {
return null;
}
}
}
类产品扩展了React.Component{
建造师(道具){
超级(道具);
此.state={
状态:“已创建”
};
}
componentDidUpdate(prevProps){
如果(
this.props.parentState==“已删除”&&
this.state.state==“已创建”
) {
this.setState({state:“deleted”});
}
}
render(){
如果(this.state.state!=“已删除”){
返回(
产品。。。。。
+
);
}否则{
返回null;
}
}
}
my ProductList.js
class ProductList extends React.Component {
constructor(props) {
super(props);
this.state = {
products: [],
state: "created"
};
}
componentDidMount() {
let newProducts = [...this.state.products];
newProducts.push(
<Product
key={0}
addNewProduct={this.addNewProduct}
parentState={this.state.state}
/>
);
this.setState({ products: newProducts });
}
addNewProduct = () => {
let length = this.state.products.length;
const newProducts = [
...this.state.products,
<Product
key={length}
addNewProduct={this.addNewProduct}
parentState={this.state.state}
/>
];
this.setState({ products: newProducts });
};
deleteAll = () => {
this.setState({ state: "deleted" });
};
render() {
return (
<div>
{this.state.products}
<button style={{ marginTop: "20px" }} onClick={this.deleteAll}>
Delete All
</button>
</div>
);
}
}
类ProductList扩展了React.Component{
建造师(道具){
超级(道具);
此.state={
产品:[],
状态:“已创建”
};
}
componentDidMount(){
让newProducts=[…this.state.products];
新产品(
);
this.setState({products:newProducts});
}
addNewProduct=()=>{
设长度=this.state.products.length;
常数新产品=[
…这个州的产品,
];
this.setState({products:newProducts});
};
deleteAll=()=>{
this.setState({state:“deleted”});
};
render(){
返回(
{this.state.products}
全部删除
);
}
}
这不会更新孩子们,我也不知道为什么。我想这是因为列表是动态的。我尝试使用一个静态列表,效果很好(代码如下)
ProductListStatic.js
class ProductListStatic extends React.Component {
constructor(props) {
super(props);
this.state = {
products: [],
state: "created"
};
}
deleteAll = () => {
console.log("delete all");
this.setState({ state: "deleted" });
};
render() {
let products = [
<Product
key={0}
addNewProduct={this.addNewProduct}
parentState={this.state.state}
/>,
<Product
key={1}
addNewProduct={this.addNewProduct}
parentState={this.state.state}
/>
];
return (
<div>
{products}
<button style={{ marginTop: "20px" }} onClick={this.deleteAll}>
Delete All
</button>
</div>
);
}
}
类ProductListStatic扩展了React.Component{
建造师(道具){
超级(道具);
此.state={
产品:[],
状态:“已创建”
};
}
deleteAll=()=>{
控制台日志(“全部删除”);
this.setState({state:“deleted”});
};
render(){
让产品=[
,
];
返回(
{产品}
全部删除
);
}
}
下面是一个演示:
anynoe知道为什么它不适用于动态产品吗?问题是状态数组中的JSX元素不知道在父元素重新渲染时需要重新渲染它们。在静态版本中,子对象直接在JSX中创建,因此重新渲染的行为是正常的。将子对象的数据存储在状态数组中,然后在每次渲染时在该状态数组上调用
.map
来创建它们,这是一个合理的解决方案
除此之外,总体设计似乎不必要地复杂。我不认为childProduct
s应该关心它们何时呈现,或者是否应该在父级中添加一个产品,并从子级回调。将所有这些信息保存在父级中要简单得多。呈现可以是隐式的——如果我们想要一个新项目,请将其推送到产品/项目数组中,如果我们想要清除所有项目,请将数组设置为[]
。不需要此.state.state
以下是概念证明:
const mockProduct=()=>({
姓名:[
“苹果”、“香蕉”、“樱桃”、“猕猴桃”,
“西瓜”、“菠萝”、“蓝莓”
][~~(Math.random()*7)],
价格:~~(Math.random()*5)+0.99
});
const Product=props=>
{props.name}
{props.price}
;
类产品扩展了React.Component{
建造师(道具){
超级(道具);
this.state={products:[mockProduct()]};
this.addNewProduct=this.addNewProduct.bind(this);
this.deleteAll=this.deleteAll.bind(this);
}
addNewProduct(){
this.setState(state=>({
产品:state.products.concat(mockProduct())
}));
}
deleteAll(){
this.setState({products:[]});
}
render(){
返回(
{this.state.products.map((e,i)=>
+
)}
全部删除
);
}
}
render(,document.body)代码>
您能在问题中发布相关代码吗?沙箱可能会随着时间的推移而改变或下降,使问题对未来的访问者毫无用处。您也需要删除产品,单独设置状态并不能真正起作用。setState({state:“deleted”,products:[]);有一件事,在代码沙箱中,您混合了UI状态管理(应该只关注数据类型(如对象、数字、布尔值等)在呈现JSX时。不要将JSX置于UI状态。UI状态应该只包含可序列化的数据类型,原因有很多,包括React的工作方式。因此,在渲染函数中,映射状态以返回JSX,并且无论在何处调用setState,都要确保其数据类型是poc的JavaScriptHnx ggorien的本机数据类型。如您所说如果我们想全部删除,则不需要childs state。但是,我想为这些childs添加一个state(产品名称和价格)在列表“全部发送”中添加一个新按钮。当用户单击它时,它会在每个子项上触发sendToServer函数以保存产品。在这种情况下,我不知道如何更改我的设计以使用您的设计?我仍然会在父项中添加“全部发送”按钮,因此我认为此示例仍然与该设计相关。它与“全部删除”相同除了代替(或补充)c之外