Javascript React卸载子组件的方式是什么?

Javascript React卸载子组件的方式是什么?,javascript,reactjs,react-state-management,react-component-unmount,Javascript,Reactjs,React State Management,React Component Unmount,我对React有点生疏,但当我学习componentWillUnmount()方法时,我发现了一个我无法理解的行为 let myArray = [1,2,3,4,5,6]; class List extends React.Component { constructor() { super() this.state = { list: [] }; } componentDidMount() { this.setState({list:

我对React有点生疏,但当我学习componentWillUnmount()方法时,我发现了一个我无法理解的行为

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"))
考虑一下这个脚本(这里是小提琴->):

让myArray=[1,2,3,4,5,6];
类列表扩展了React.Component{
构造函数(){
超级()
此.state={
名单:[]
};
}
componentDidMount(){
this.setState({list:myArray});
}
render(){
返回(
我的名单
    { this.state.list.map((项,索引)=>( 项目{Item} )) }
) } handleDelete=(值)=>{ log(“原始列表:”,this.state.list); console.log(“处理项目删除”+值); 让newState={…this.state}; newState.list=newState.list.filter((v)=>v!==value); log(“新列表:”,newState.list); this.setState(newState); } } 类项扩展了React.Component{ render(){ 返回(
  • 项{this.props.value}
  • ); } 删除=()=>{ console.log('请删除项'+此.props.value); this.props.onDeleteItem(this.props.value); } 组件将卸载(){ log(“卸载项”+此.props.value); } } ReactDOM.render(,document.querySelector(“#app”))
    正如您可以签入JSFiddle.net脚本(使用开发人员的控制台)一样,每当您单击一个项目时,列表组件就会从其状态中删除该值,并重新呈现其余的项目。到现在为止,一直都还不错。问题是,在卸载之前,项组件总是有最后一个项的道具,比如这些道具是否会被覆盖或其他什么(您可以在开发人员控制台中查看)。因此,即使我删除了项目#3(或任何一个),componentWillUnmount()上的“this.props.value”始终为=6,而我预期为=3

    我猜,无论出于何种性能原因,React都是从DOM中删除最后一项,然后重新呈现其余项。这是预期的行为吗?如果是这样的话,您能否参考一些文档和/或告诉我如何在卸载之前保留要删除的项目的原始实例?我试图将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"))
    
    让myArray=[1,2,3,4,5,6];
    类列表扩展了React.Component{
    构造函数(){
    超级()
    此.state={
    名单:[]
    };
    }
    componentDidMount(){
    this.setState({list:myArray});
    }
    render(){
    返回(
    我的名单
    
      { this.state.list.map((项,索引)=>( 项目{Item} )) }
    ) } handleDelete=(值)=>{ log(“原始列表:”,this.state.list); console.log(“处理项目删除”+值); 让newState={…this.state}; newState.list=newState.list.filter((v)=>v!==value); log(“新列表:”,newState.list); this.setState(newState); } } 类项扩展了React.Component{ render(){ 返回(
  • 项{this.props.value}
  • ); } 删除=()=>{ console.log('请删除项'+此.props.value); this.props.onDeleteItem(this.props.value); } componentDidUpdate(){ log(“incdu”,this.props.value); } 组件将卸载(){ log(“卸载项”+此.props.value); } } ReactDOM.render(,document.querySelector(“#app”))
    我在这里所做的唯一更改是将适当的标识符(这里是项本身)作为键传递

    Item{Item}
    

    您可以参考

    发生这种情况是因为在项目列表中使用索引作为键。这是一种反模式。如需了解更多详细信息,请阅读快速、清晰的答案,它就像一个符咒。谢谢我现在爱你,我不知道。。。非常感谢你的链接,我现在明白了!
    <Item key={`${item}`} value={item} onDeleteItem={this.handleDelete}>Item {item}</Item>