【问题标题】:Component List don't update state after deleting one item删除一项后组件列表不更新状态
【发布时间】:2018-05-25 18:24:36
【问题描述】:

我在尝试更新通过映射字符串列表创建的有状态组件列表时遇到问题。当我通过对数组进行切片以按其索引删除元素来删除其中一个组件时,问题就出现了。

每个组件都有自己的状态,我从 API 中获取。问题是当我删除数组的一个元素时,下一个组件的状态与我删除的那个组件重叠。

我的代码看起来与此类似:

class MyDashboard extends React.Component {
 constructor(props){
  super(props);
  this.state = {
    activeItems: [0,1,2,3],
  }
 this.removeItem = this.removeItem.bind(this);
}

removeItem(indx){
 let tempItems= this.state.activeItems;
 tempItems.splice(indx,1);
 this.setState({activeItems:tempItems});
}

render(){
    let conditionalDash;
    let conditionalComponent;
    let temporalArray = this.state.activeEntries.map((entry , i) => {
      return  (<MyDash key={i} index {i}/> removeItem={this.removeItem});
});

render(){
 return (
   <div id='dashContainer'>
    {temporalArray}
   </div>
  )
 } 
}

在我的 MyDashComponent 我有这样的东西:

class MyDash extends React.Component{
constructor(props){
  super(props);
  this.state={
   fetchedData:null,
  }
 }
componentDidMount(){
  API.fetchData(this.props.index).then(response => {
    this.setState({fetchData:response.data})
  )
}
render(){
 return(
  <div> {this.props.index} {this.state.fetchedData}</div>
 )
}
}

我有什么遗漏吗?

我得到的行为是,当我删除 this.state.activeItems[2] 时,此元素的状态与前一个组件相同。我期待元素 [2] 的状态与具有元素 [3] 的状态相同。

编辑: 我忘了说的是,MyDash 组件的 props 是正确的,只是不属于该组件的状态,它来自已删除的组件。

感谢您的阅读,我希望有人可以帮助我。

【问题讨论】:

    标签: javascript arrays reactjs components state


    【解决方案1】:

    我发现错误是我正在使用的列表的键,它是 map 方法的索引,我读到它必须是唯一键。幸运的是,这修复了渲染动作并且状态不再重叠。

    【讨论】:

      【解决方案2】:

      谁混合了行为或slicesplice

      slice 返回一个新数组,而splice 修改现有数组

      根据 MDN 文档:

      splice: splice() 方法通过以下方式更改数组的内容 删除现有元素和/或添加新元素。

      语法:array.splice(start, deleteCount)

      slice: slice() 方法返回一个浅表副本的一部分 数组到一个新的数组对象中,从开始到结束(结束不是 包括)。原数组不会被修改。

      语法:

      arr.slice()
       arr.slice(begin)
       arr.slice(begin, end)
      

      您可以将代码更改为

      removeItem(indx){
         let tempItems= this.state.activeItems;
         tempItems.splice(indx,1);
         this.setState({ activeItems:tempItems });
      }
      

      另外你不应该直接改变状态,你应该创建一个状态数组的副本然后更新它。

      removeItem(indx){
         let tempItems= [...this.state.activeItems]; // this is do a shallow copy, you could use something else depending on your usecase
         tempItems.splice(indx,1);
         this.setState({ activeItems:tempItems });
      }
      

      【讨论】:

      • 我的错,我使用的是拼接方法,我修正了错字。像使用扩展运算符那样创建 tempItems 与像我一样将其创建为副本有什么区别?我会试试你的答案,谢谢
      • 在您的情况下,您将状态数组的引用分配给 tempItems,然后修改 tempItems,也会修改状态数组,但是,当您再次 setState 时,它​​不会产生影响。但是您应该克隆您的状态数组,然后将其修改为模式
      • 有道理,谢谢解释,我会尽快尝试?
      【解决方案3】:

      您也可以使用Array.prototype.filter 删除该项目:

      removeItem(idx) {
        this.setState({
          activeItems: this.state.activeItems.filter((_, index) => index !== idx)
        });
      }
      

      removeItem(idx) {
        this.setState(prevState => ({
          activeItems: prevState.activeItems.filter((_, index) => index !== idx)
        }));
      }
      

      【讨论】:

        猜你喜欢
        • 2017-06-24
        • 1970-01-01
        • 2019-10-11
        • 2020-07-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多