Реакция: Как изменить состояние на основе массива без индекса или уникального идентификатора? - PullRequest
2 голосов
/ 16 марта 2019

Допустим, у меня есть компонент с вкладками.Каждая вкладка представляет объект человека.Пользователь может переключать активную вкладку, изменять или удалять каждую и даже изменять их порядок:

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 })
}

Проблема с этим заключается в том, что она опирается на индекс данной вкладки.Но что если индекс вкладок изменится, если я предоставлю, скажем, возможность переключения порядка вкладок (как это делают браузеры для своих вкладок).

Или что, если мне нужно зарегистрировать некоторый обратный вызов для операции a-sync, который может быть вызван, когда соответствующий человек находится на другой вкладке (возможно, вкладка была перемещена с 1 на 0, к тому времени, когдабыл вызван обратный вызов)?

Есть ли способ просто положиться на ссылку на объект , независимо от идентификатора, индекса или любого другого «идентификатора», что делает код намного более сложным, чем ему нужнобыть?

Для тех, кто знаком с VueJS и Angular, я уверен, что вы знаете, как легко модифицировать объекты, поскольку вам не нужно возвращать новое дерево состояний при каждом изменении.

1 Ответ

3 голосов
/ 16 марта 2019

Если вы меняете порядок массива, вы не можете полагаться на массив 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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...