我正在尝试使用ReactJS构建一个动态组件。因此,我有一个产品列表,每当用户想要添加新产品时,他都会单击+按钮。这将创建一个新产品并将其添加到列表中。列表中有一个名为delete all的按钮,用于删除所有产品。
要删除所有产品,我在产品列表中使用了一个在组件创建时使用“创建”初始化的状态,当用户单击“全部删除”时,我将其更改为“已删除”以使用ComponentWillUpdate更新子项(产品)回调。
这是一些代码:
index.js
render() {
return (
<div className="App">
<h1>Dynamic List</h1>
<ProductList />
<hr />
<h1>Static List</h1>
<ProductListStatic />
</div>
);
}
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;
}
}
}
我的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>
);
}
}
这不会更新孩子,我也不知道为什么。我认为这是因为清单是动态的。我尝试使用静态列表进行尝试,并且效果很好(下面的代码)。
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>
);
}
}
这是一个演示:SandBox live dome
任何人都知道为什么它不能与动态产品一起使用吗?
答案 0 :(得分:2)
问题在于状态数组中的JSX元素不知道在父级重新渲染时需要重新渲染它们。在静态版本中,子代直接在JSX中创建,因此重新渲染的行为是正常的。合理的解决方案是在子状态数组中存储子项的数据,然后通过在每个渲染器上在该状态数组上调用construct
来创建子项。
除此之外,整体设计似乎不必要地复杂。我认为孩子//ADD LINE BREAK
add_filter( 'the_title', 'custom_the_title', 10, 2 );
function custom_the_title( $title, $post_id ) {
$post_type = get_post_field( 'post_type', $post_id, true );
if( $post_type == 'product' || $post_type == 'product_variation' )
$title = str_replace( '|', '<br/>', $title ); // we replace '|' by '<br>'
return $title;
}
不必担心何时渲染,或者是否应该通过孩子的回调将产品添加到父亲中。将所有这些信息保留在父级中要简单得多。渲染可能是隐式的-如果我们想要一个新商品,请将其推到product / items数组中,如果我们想清除所有商品,请将数组设置为.map
。不需要Product
。
这是一个概念证明:
[]
this.state.state
如果您计划为每种产品添加其他按钮和数据,则可能需要一个行容器。然后,当行应将更改应用于项目时,回调将成为行向父母发出信号的必要条件。这取决于您的设计目标,目前还为时过早(从const mockProduct = () => ({
name: [
"apple", "banana", "cherry", "kiwi",
"watermelon", "pineapple", "blueberry"
][~~(Math.random()*7)],
price: ~~(Math.random() * 5) + 0.99
});
const Product = props =>
<div>
<span>{props.name}</span>
<span>{props.price}</span>
</div>
;
class Products extends React.Component {
constructor(props) {
super(props);
this.state = {products: [mockProduct()]};
this.addNewProduct = this.addNewProduct.bind(this);
this.deleteAll = this.deleteAll.bind(this);
}
addNewProduct() {
this.setState({
products: this.state.products.concat(mockProduct())
});
}
deleteAll() {
this.setState({products: []});
}
render() {
return (
<React.Fragment>
<div>
{this.state.products.map((e, i) =>
<div
style={{display: "flex"}}
key={`${i}-${e.name}`}
>
<Product name={e.name} price={e.price} />
<button onClick={this.addNewProduct}>+</button>
</div>
)}
</div>
<div>
<button onClick={this.deleteAll}>delete all</button>
</div>
</React.Fragment>
);
}
}
ReactDOM.render(<Products />, document.body);
除去渲染问题之后,没有太多理由证明其存在。)