useEffect в React выполняется в бесконечном l oop, когда массив передается как зависимость - PullRequest
0 голосов
/ 07 марта 2020

Когда следующий код выполняется в компоненте React, он вызывает бесконечное l oop. Почему передача массива в качестве зависимости useEffect (в данном случае args) приводит к тому, что это происходит? Как я могу остановить бесконечное происшествие? Код должен запускаться только один раз.

Я прочитал, что могу использовать [args.length], чтобы не допустить этого, но тогда правило ESLint react-hooks/exhaustive-deps выдает ошибку, поэтому я хочу избежать этого, чтобы way.

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

export default function Home() {
  const args = ['a'];
  const [value, setValue] = useState(['b']);

  useEffect(() => {
    setValue(['c']);
  }, [args]);

  console.log('value', value);
}

Обратите внимание, что в приведенном выше коде я даже не использую или не изменяю args вообще, в обратном вызове useEffect.

Если я изменяю значение из args в строку, например const args = 'a', тогда нет бесконечного l oop. Таким образом, проблема возникает, когда зависимость представляет собой массив.

Ответы [ 2 ]

1 голос
/ 07 марта 2020

Проблема в том, что любое изменение args вызовет запуск вашего эффекта. В этот момент вы setValue(args), поэтому args снова меняется. Это приведет к тому, что ваш эффект снова запустится ... отсюда и бесконечный l oop.

Если вы установите args на ту же строку, что была до того, как она не будет зарегистрирована как изменение, если они совпадают с способ реагирования обнаруживает изменения. Это не будет работать для массива или объекта. {test: 'a'} !== {test: 'a'} и ['a'] !== ['a'], но 'a' === 'a' и 1 === 1.

Я также столкнулся с вашей проблемой. В итоге я отключил правило react-hooks/exhaustive-deps. Но у меня есть больше данных для вас. Я изо всех сил пытался использовать это правило некоторое время.

Этот пост , который я сделал, очень похож на ваш вопрос. Конечный результат заключается в том, что вы должны использовать setState как функцию (ie. setState(oldState => oldState) из вашего примера), после чего старое состояние не обязательно должно быть зависимостью, или useReducer, который также производит тот же эффект.

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

Четвертое решение в 1-м посте описывает, как можно агрессивно избежать этой проблемы, но в итоге я решил использовать правило react-hooks/exhaustive-deps и отключить это строка за строкой, когда я намеренно удаляю зависимости, которые мне не нужны. Я не согласен с тем, что это должно быть правилом после всего этого.

Проблема, которую вы пытаетесь сделать, заключается в том, чтобы сбалансировать требование React о том, что useState и useReducer чисто с требованием исчерпывающих падений. Я думаю, что это приводит к большой работе по удовлетворению этих требований по сравнению с реальной производительностью.

0 голосов
/ 07 марта 2020

Использование useRef исправило эту проблему для меня:

const args = useRef(['a']);
const [value, setValue] = useState(['b']);

useEffect(() => {
  setValue(['c']);
}, [args]);

console.log('value', value);

И значение args можно использовать в обратном вызове useEffect с args.current.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...