Почему имеет значение, изменяю ли я состояние в React useState hook?

#javascript #reactjs

#javascript #reactjs

Вопрос:

Я везде читал, что изменяющееся состояние в React может вызвать проблему, например, компонент не будет повторно отображаться при обновлении состояния, но следующий код работает отлично. Компонент повторно отображает каждый раз, когда происходит обновление состояния.

 import React, { useState, useEffect } from "react";

const Mutator = () => {
  const [checks, setChecks] = useState({ 66: false });

  const rows = [{ id: 23 }, { id: 33 }, { id: 44 }, { id: 55 }];

  useEffect(() => {
    console.log("check updates", checks);
  }, [checks]);

  const mutateMyCheck = () => {
    rows.forEach((row, i) => {
      checks[row.id] = checks[row.id] ? checks[row.id]   i : 1;
    });

    setChecks({ ...checks });
  };
  return (
    <div>
      <button onClick={mutateMyCheck}>Check</button>
      <div>{JSON.stringify(checks)}</div>
    </div>
  );
};
  

Какой смысл тогда не изменять состояние? Или когда это действительно имеет эффект?

Ответ №1:

Вы изменяете состояние напрямую, но вы также возвращаете новый объект через распространение объекта:

 setChecks({ ...checks });
  

Поскольку это создает новый объект, компонент повторно отображает.

Комментарии:

1. Это. Кроме того, нет абсолютно никаких причин изменять состояние в прилагаемом примере. То же самое может быть достигнуто с помощью Array.prototype.map() или Array.prototype.reduce()

2. Правда, хотя это скорее предпочтение стиля, reduce на самом деле не делает его чище, поэтому не упоминал — rows.reduce((obj, row, i) => ({ ...obj, [row.id]: checks[row.id] ? checks[row.id] i : 1, }), {}) Также, если строки находятся в 1000-х годах, я бы не стал распространять каждую итерацию подобным образом, но каждый раз возвращал бы один и тот же объект (мутированный), поскольку он значительно медленнее, поэтому в случае 1000s было бы похоже на цикл изменения, чтобы быть эффективным.

3. В этом точном случае это решение о стиле. Но если учесть возможные последствия мутаций состояния, оно перестает быть единым; ваше состояние отличается от того, что отобразил DOM, или представьте, что у вас подключено несколько хуков. Или просто подумайте о путанице, которую это вносит.

Ответ №2:

  mutateMyCheck(); mutateMyCheck();
  

Это не увеличит количество проверок в два раза.

В этом случае вам следует использовать редуктор.