Скажем, у меня есть родительский компонент, который отображает дочерний компонент, и все, что делает дочерний элемент, - это сохранять какое-то состояние и запускать обработчик onChange, если его собственное состояние изменяется. См. Код ниже или ...

0
Sventies 15 Дек 2020 в 16:59

1 ответ

Лучший ответ

Вы должны обернуть метод handleChange хуками useCallback, чтобы он был создан один раз.

const handleChange = useCallback(() => setState(state + 1),[]);

Бесконечный цикл возникает из-за того, что вы добавили метод onChange в качестве зависимости для useEffect в компоненте <Comp />.

UseEffect принимает массив зависимостей и запускает эффект при изменении одной из зависимостей.

Поскольку вы добавили обработчик onchange в качестве зависимости, каждый раз при повторной визуализации родительского компонента создается новый экземпляр метода handleChange, который не равен предыдущему методу handlechange.

Процесс рендеринга компонентов будет таким:

  1. Компонент <App /> создает метод handleChange и передает его <Comp />
  2. Useffect в <Comp /> будет вызываться после первоначального рендеринга, и оттуда будет вызван метод handleChange компонента <App />.
  3. состояние изменяется в компоненте <App /> и повторно отображает его. При повторном рендеринге создается новый экземпляр handleChange, который передается через свойство onChange компоненту <Comp />.
  4. Поскольку значение в предыдущей и новой опоре onChange отличается, будет запущен useEffect, который снова обновит состояние родительского компонента, и этот цикл продолжится.

Чтобы предотвратить это, метод handleChange должен быть заключен в useCallback. Функция обратного вызова, переданная в ловушку useCallback, будет запоминаться, поэтому, когда дочерний компонент сравнивает старую и новую опоры, они остаются равными.

{} === {}  // false
[] === []  // false
(() => {}) == (() => {})  //false
1
Vivek 15 Дек 2020 в 18:20