Реагировать: как мне избавиться от этой ошибки «Максимальная глубина обновления превышена»

У меня есть компонент с состоянием, которое является объектом, и я хотел установить состояние в useEffect, где он перебирает ключи объекта для обновления состояния. Проблема в том, что это дает мне ошибку для бесконечных циклов.

Неперехваченная ошибка: превышена максимальная глубина обновления. Это может произойти, когда компонент неоднократно вызывает setState внутри componentWillUpdate или componentDidUpdate. React ограничивает количество вложенных обновлений, чтобы предотвратить бесконечные циклы.

Я решил, что это потому, что список ключей, который я использую в качестве dep для useEffect, представляет собой массив, и он меняется каждый раз, когда компонент перерисовывается, потому что это не примитивный тип. Итак, я записал это, используя useMemo, но это все еще не работает, тогда я понял, что это может быть из-за того, что dep в памятке - это состояние, которое также НЕ является примитивным типом, то есть объектом, поэтому он каждый раз отличается, что приводит к список ключей каждый раз разный даже с useMemo

Вот код

const ManageIndexingPage: React.FC = () => {
  const dispatch = useDispatch();
  const stateFromStore = useSelector(
    (state: RootState) => state.settings.indexing
  );
  const [indexingConfig, setIndexingConfig] = useState<IndexingConfig>(
    getDefaultIndexingConfig()
  );

  const listOfKeys = useMemo(
    () => Object.keys(indexingConfig) as Array<keyof typeof indexingConfig>,
    [indexingConfig]
  );

  useEffect(() => {
    dispatch(getIndexingConfig());
  }, [dispatch]);

  useEffect(() => {
    listOfKeys.forEach((key) =>
      setIndexingConfig((prevState) => ({
        ...prevState,
        [key]: stateFromStore[key]
      }))
    );
  }, [stateFromStore, listOfKeys]);
};

//....

function getDefaultIndexingConfig(): IndexingConfig {
  return {
    thingIndexingEnabled: false,
    thingConnectivityEnabled: false,
    thingDeviceShadowEnabled: false,
    thingGroupIndexingEnabled: false
  };
}

Здесь listOfkeys на самом деле просто массив строк, то есть ["thingIndexingEnabled", "thingConnectivityEnabled"...]. Поэтому, если бы я жестко запрограммировал это и использовал это в useEffect, этой ошибки не было бы, и все в порядке, т.е.

useEffect(() => {
    ["thingIndexingEnabled", "thingConnectivityEnabled"...].forEach((key) =>
      setIndexingConfig((prevState) => ({
        ...prevState,
        [key]: stateFromStore[key]
      }))
    );
  }, [stateFromStore]);

Как мне избавиться от этой ошибки без жесткого кодирования списка ключей? Или есть лучший способ сделать это?


person Joji    schedule 03.09.2020    source источник


Ответы (1)


Проблема здесь:

 useEffect(() => {
   ....
      setIndexingConfig((prevState) => ({
        ...prevState,
        [key]: stateFromStore[key]
      }))
    );
  }, [stateFromStore, listOfKeys]);

Вы не должны устанавливать состояние в useEffect(), потому что это зависит от того, что каждое изменение приведет к повторному выполнению useEffect. setThe state из другого места или используйте useRef, так как это не вызывает повторного рендеринга.

person MD10    schedule 03.09.2020
comment
это неправда. использование setState в useEffect не обязательно приведет к бесконечному циклу, если состояние, которое находится в состоянии, не является частью зависимостей useEffect - person Joji; 05.09.2020
comment
Я сказал, что это вызвано тем, что у эффекта есть зависимости, которые обновляются в setState. - person MD10; 05.09.2020