React:如何在没有索引或唯一标识符的情况下修改基于数组的状态?

时间:2019-03-16 12:09:07

标签: javascript reactjs immutability

假设我有一个选项卡式组件。每个选项卡均显示一个人员对象。用户可以切换活动标签,修改或删除每个标签,甚至更改其顺序:

state={
  activeTab:0,
  tabs:[
    {
      name:'John',
      age:34

    },
    {
      name:'Bob',
      age:31

    },
  ]
}

假设我要修改特定选项卡(人)的字段之一。我可以使用此功能:

modifyTab = (index, prop, value) => {

  const tabs = [...this.state.tabs];

  const tab = tabs[index];

  tab[prop] = value;

  this.setState({ tabs })
}

这个问题是,它依赖于给定标签的索引。但是,如果选项卡索引发生了变化(如果我提供的话),可以切换选项卡的顺序呢?(就像浏览器为它们的选项卡所做的那样)。

或者如果我需要为异步操作注册一些回调,当相关人员坐在另一个选项卡中时可能会调用该回调(也许在调用回调时,选项卡已从1移至0 )?

是否有任何方法可以仅依靠对象引用而与id,索引或任何其他“标识符”无关,这会使代码变得比所需复杂得多。

对于那些熟悉VueJS和Angular的人,我确定您知道修改对象是多么容易,因为您无需在每次更改时都返回新的状态树。

1 个答案:

答案 0 :(得分:3)

如果要更改数组的顺序,则在渲染时,不能依赖数组index作为key道具。解决此问题的一种常见方法是向数组中的每个对象添加唯一属性,然后使用该属性,例如id

将整个对象引用传递给modifyTab会很好。您可以使用简单的indexOf找出数组中的哪个对象。

示例

class App extends React.Component {
  state = {
    tabs: [
      {
        name: "John",
        age: 34,
        id: 1
      },
      {
        name: "Bob",
        age: 31,
        id: 2
      }
    ]
  };

  modifyTab = (tab, prop, value) => {
    this.setState(prevState => {
      const tabs = [...prevState.tabs];
      const index = tabs.indexOf(tab);

      tabs[index] = { ...tabs[index], [prop]: value };

      return { tabs };
    });
  };

  render() {
    return (
      <div>
        {this.state.tabs.map(tab => (
          <span
            key={tab.id}
            onClick={() => this.modifyTab(tab, "name", Math.random())}
            style={{ margin: '0 10px' }}
          >
            {tab.name}
          </span>
        ))}
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="root"></div>