【问题标题】:Which is the way React unmounts child components?React 卸载子组件的方式是什么?
【发布时间】:2020-04-14 17:12:58
【问题描述】:

我是 React 的新手,但是当我学习 componentWillUnmount() 方法时,我发现了一个我无法理解的行为。

考虑这个脚本(这是小提琴 -> 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 组件始终具有最后一个 item 的 props,例如,如果这些将被覆盖或其他情况(您可以在开发人员的控制台中查看这一点)。因此,即使我要删除第 3 项(或其他任何一项),componentWillUnmount() 上的“this.props.value”总是 = 6,而我期望 = 3。

我猜,无论出于何种性能原因,React 都会从 DOM 中删除最后一项并重新渲染其余部分。这种行为是预期的吗?如果是这样,您能否参考一些文档和/或告诉我如何在卸载之前保留该项目的原始实例?我尝试将 props.value 存储在项目状态中,但也不起作用。

提前致谢。

【问题讨论】:

    标签: javascript reactjs react-state-management react-component-unmount


    【解决方案1】:

    你得到这个的原因是因为你将数组的索引作为键传递。相反,如果您传递一个有效的唯一标识符,则不会发生这种情况。

    请运行这段代码,你会明白的。

    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>
    

    您可以参考Understanding unique keys for array children in React.js

    【讨论】:

    • 快速而干净的答案,就像一个魅力。谢谢!我现在爱你。
    【解决方案2】:

    这是因为在您的项目列表中使用索引作为键。这是一种反模式。更多详情请阅读here

    【讨论】:

    • 我不知道...非常感谢您的链接,我现在明白了!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-08
    • 2019-11-14
    • 1970-01-01
    • 2021-04-26
    • 1970-01-01
    • 1970-01-01
    • 2020-09-28
    相关资源
    最近更新 更多