useState принимает обновления, если ссылка на объект не изменяется - PullRequest
0 голосов
/ 27 января 2019

Я думал, что useState нужно иметь новое значение, чтобы он мог принимать обновления:

Я создал codesandbox , чтобы проиллюстрировать, что я имею в виду.

У меня есть вложенная структура данных, подобная этой

   const state = {
      name: "parent",
      data: {
        isExpanded: false,
        children: [
          { name: "one", data: { isExpanded: false } },
          { name: "two", data: { isExpanded: false } },
          { name: "three", data: { isExpanded: false } }
        ]
      }
    };

Затем я использую useState, чтобы вызвать рендеринг при изменении состояния:

function App() {
  const [tree, setTree] = useState(state);

  const toggleExpanded = node => {
    node.data.isExpanded = !node.data.isExpanded;

    setTree(tree);
  };

  return (
    <div className="App">
      <h1>IsExpanded</h1>
      {tree.data.children.map(child => (
        <button onClick={() => toggleExpanded(child)}>
          {child.name} - {child.data.isExpanded ? "on" : "off"}
        </button>
      ))}
    </div>
  );
}

Я использую одну и ту же ссылку каждый раз при вызовеsetTree и обновления происходят.

Я думал, что каждый раз для этого требуется новая ссылка?

Возможно, я что-то упускаю, но обновление не происходит с той же ссылкой.

Ответы [ 2 ]

0 голосов
/ 27 января 2019

Это ожидаемое поведение.В этом случае установщик, возвращаемый useState, работает так же, как и не подключенный setState.Любое его выполнение вызовет повторную визуализацию, и не имеет значения, является ли это той же ссылкой на объект или нет.

Если вы только что сделали:

node.data.isExpanded = !node.data.isExpanded;

без вызова setTree, тогда визуальное обновление не произойдет, поскольку повторный рендеринг не будет запущен.

Часто рекомендуется избегать обновлений состояния путем изменения существующего объекта состояния, поскольку это может привести к определенным типам ошибок (например,если у вас есть какая-либо логика, которая сравнивает предыдущее состояние с новым состоянием, они будут казаться всегда одинаковыми, если вы вносите изменения, изменяя существующие объекты).А возможные тонкие проблемы, к которым это может привести, скорее всего, расширятся с будущими функциями параллельного режима React, но React не мешает вам сделать это.

0 голосов
/ 27 января 2019

Желательно иметь неизменное состояние, потому что этот подход идиоматичен для React.Но это будет работать и с изменением существующего государства.setTree(tree) запускает обновление, не имеет значения, является ли tree тем же или другим.

Он работает так же, как setState(sameState) в компонентах класса, что аналогично forceUpdate, чтокак правило, не рекомендуется.

...