React 卸载子组件的方式是什么?
Which is the way React unmounts child components?
我是 React 的新手,但是当我学习 componentWillUnmount() 方法时,我发现了一个我无法理解的行为。
考虑这个脚本(这里是 fiddle -> https://jsfiddle.net/ockhamsblade/4zf5tq2h/37/):
let myArray = [1,2,3,4,5,6];
class List extends React.Component {
constructor() {
super()
this.state = {
list: []
};
}
componentDidMount() {
this.setState({list:myArray});
}
render() {
return (
<div>
<h1>My list</h1>
<ul>
{
this.state.list.map((item, index) => (
<Item key={index} value={item} onDeleteItem={this.handleDelete}>Item {item}</Item>
))
}
</ul>
</div>
)
}
handleDelete = (value) => {
console.log("Original list: ", this.state.list);
console.log("Handling delete of item " + value);
let newState = {...this.state};
newState.list = newState.list.filter((v) => v !== value);
console.log("New list: ", newState.list);
this.setState(newState);
}
}
class Item extends React.Component {
render() {
return (<li><button type="button" onClick={this.delete}>Item {this.props.value}</button></li>);
}
delete = () => {
console.log('Please remove item ' + this.props.value);
this.props.onDeleteItem(this.props.value);
}
componentWillUnmount() {
console.log("Unmounting item " + this.props.value);
}
}
ReactDOM.render(<List />, document.querySelector("#app"))
正如您可以签入 JSFiddle.net 脚本(使用开发人员的控制台),每当您单击一个项目时,List 组件都会从其状态中删除该值并重新呈现剩余的项目。到目前为止,一切都很好。事情是,在被卸载之前,Item 组件总是有最后一个项目的道具,例如这些道具是否会被覆盖或其他什么(您可以在开发人员的控制台中查看)。因此,即使我要删除第 3 项(或任何一项),componentWillUnmount() 上的 "this.props.value" 始终 = 6,而我期望 = 3.
我猜想,无论出于何种性能原因,React 都会从 DOM 中删除最后一项并重新渲染其余项。这种行为是预期的吗?如果是,能否请您参考一些文档 and/or 告诉我如何在卸载之前保持被删除的项目的原始实例?我尝试将 props.value 存储在项目状态上,但也不起作用。
提前致谢。
你得到这个的原因是因为你将数组的索引作为键传递。相反,如果您传递有效的唯一标识符,则不会发生这种情况。
请运行这段代码你会明白的。
let myArray = [1,2,3,4,5,6];
class List extends React.Component {
constructor() {
super()
this.state = {
list: []
};
}
componentDidMount() {
this.setState({list:myArray});
}
render() {
return (
<div>
<h1>My list</h1>
<ul>
{
this.state.list.map((item, index) => (
<Item key={`${item}`} value={item} onDeleteItem={this.handleDelete}>Item {item}</Item>
))
}
</ul>
</div>
)
}
handleDelete = (value) => {
console.log("Original list: ", this.state.list);
console.log("Handling delete of item " + value);
let newState = {...this.state};
newState.list = newState.list.filter((v) => v !== value);
console.log("New list: ", newState.list);
this.setState(newState);
}
}
class Item extends React.Component {
render() {
return (<li><button type="button" onClick={this.delete}>Item {this.props.value}</button></li>);
}
delete = () => {
console.log('Please remove item ' + this.props.value);
this.props.onDeleteItem(this.props.value);
}
componentDidUpdate(){
console.log("incdu",this.props.value);
}
componentWillUnmount() {
console.log("Unmounting item " + this.props.value);
}
}
ReactDOM.render(<List />, document.querySelector("#app"))
我在这里所做的唯一更改是传递一个正确的标识符(这里是项目本身)作为键。
<Item key={`${item}`} value={item} onDeleteItem={this.handleDelete}>Item {item}</Item>
可以参考
发生这种情况是因为在您的项目列表中使用索引作为键。那是一个反模式。有关详细信息,请阅读 here
我是 React 的新手,但是当我学习 componentWillUnmount() 方法时,我发现了一个我无法理解的行为。
考虑这个脚本(这里是 fiddle -> https://jsfiddle.net/ockhamsblade/4zf5tq2h/37/):
let myArray = [1,2,3,4,5,6];
class List extends React.Component {
constructor() {
super()
this.state = {
list: []
};
}
componentDidMount() {
this.setState({list:myArray});
}
render() {
return (
<div>
<h1>My list</h1>
<ul>
{
this.state.list.map((item, index) => (
<Item key={index} value={item} onDeleteItem={this.handleDelete}>Item {item}</Item>
))
}
</ul>
</div>
)
}
handleDelete = (value) => {
console.log("Original list: ", this.state.list);
console.log("Handling delete of item " + value);
let newState = {...this.state};
newState.list = newState.list.filter((v) => v !== value);
console.log("New list: ", newState.list);
this.setState(newState);
}
}
class Item extends React.Component {
render() {
return (<li><button type="button" onClick={this.delete}>Item {this.props.value}</button></li>);
}
delete = () => {
console.log('Please remove item ' + this.props.value);
this.props.onDeleteItem(this.props.value);
}
componentWillUnmount() {
console.log("Unmounting item " + this.props.value);
}
}
ReactDOM.render(<List />, document.querySelector("#app"))
正如您可以签入 JSFiddle.net 脚本(使用开发人员的控制台),每当您单击一个项目时,List 组件都会从其状态中删除该值并重新呈现剩余的项目。到目前为止,一切都很好。事情是,在被卸载之前,Item 组件总是有最后一个项目的道具,例如这些道具是否会被覆盖或其他什么(您可以在开发人员的控制台中查看)。因此,即使我要删除第 3 项(或任何一项),componentWillUnmount() 上的 "this.props.value" 始终 = 6,而我期望 = 3.
我猜想,无论出于何种性能原因,React 都会从 DOM 中删除最后一项并重新渲染其余项。这种行为是预期的吗?如果是,能否请您参考一些文档 and/or 告诉我如何在卸载之前保持被删除的项目的原始实例?我尝试将 props.value 存储在项目状态上,但也不起作用。
提前致谢。
你得到这个的原因是因为你将数组的索引作为键传递。相反,如果您传递有效的唯一标识符,则不会发生这种情况。
请运行这段代码你会明白的。
let myArray = [1,2,3,4,5,6];
class List extends React.Component {
constructor() {
super()
this.state = {
list: []
};
}
componentDidMount() {
this.setState({list:myArray});
}
render() {
return (
<div>
<h1>My list</h1>
<ul>
{
this.state.list.map((item, index) => (
<Item key={`${item}`} value={item} onDeleteItem={this.handleDelete}>Item {item}</Item>
))
}
</ul>
</div>
)
}
handleDelete = (value) => {
console.log("Original list: ", this.state.list);
console.log("Handling delete of item " + value);
let newState = {...this.state};
newState.list = newState.list.filter((v) => v !== value);
console.log("New list: ", newState.list);
this.setState(newState);
}
}
class Item extends React.Component {
render() {
return (<li><button type="button" onClick={this.delete}>Item {this.props.value}</button></li>);
}
delete = () => {
console.log('Please remove item ' + this.props.value);
this.props.onDeleteItem(this.props.value);
}
componentDidUpdate(){
console.log("incdu",this.props.value);
}
componentWillUnmount() {
console.log("Unmounting item " + this.props.value);
}
}
ReactDOM.render(<List />, document.querySelector("#app"))
我在这里所做的唯一更改是传递一个正确的标识符(这里是项目本身)作为键。
<Item key={`${item}`} value={item} onDeleteItem={this.handleDelete}>Item {item}</Item>
可以参考
发生这种情况是因为在您的项目列表中使用索引作为键。那是一个反模式。有关详细信息,请阅读 here