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

React: How to modify an array-based state, without an index or a unique identifier?

假设我有一个选项卡式组件。每个选项卡都代表一个人对象。用户可以切换活动选项卡,修改或删除每个选项卡,甚至更改它们的顺序:

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、索引或任何其他"identifier",这使得代码比它需要的复杂得多成为?

对于那些熟悉 VueJS 和 Angular 的人来说,我相信你知道修改对象是多么容易,因为你不需要 return 一个新的状态树每一个变化。

如果要更改数组的顺序,则在渲染时不能依赖数组 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>