React Hooks useEffect, добавление зависимостей запускает бесконечный цикл

Внутри моего useEffect у меня есть зависимость реквизита (setIsValid). Когда я добавляю эту зависимость к useEffect, она попадает в бесконечный цикл.

Родитель при вызове дочернего компонента:

const setIsValid = (bool) => {
  const tmpStateCopy = Object.assign({}, state);
  tmpStateCopy.isValid = bool;

  setState(tmpStateCopy);
};

return <Child
  setIsValid = {setIsValid}
/>

В дочернем компоненте:

const { setIsValid } = props;

const [state, setState] = useState({
  transformations: [],
  duplicateIndexes: []
});

const { transformations, duplicateIndexes } = state;

useEffect(() => {
  const invalids = transformations.find(x => (x.value === '' || x.replaceWith === ''));
  const hasDuplicates = duplicateIndexes.length > 0;
  const isValid = ((invalids === undefined) && (transformations.length > 0) && !hasDuplicates);

  setIsValid(isValid)

  console.info('got triggered');
}, [state]);

Таким образом, код работает, но я всегда получаю предупреждение.

Я хочу, чтобы проверка всегда запускалась при изменении одного из значений внутри состояния (преобразования/дубликаты индексов).

Добавляя функцию setIsValid() из реквизита, она работает бесконечно.

Предупреждение выглядит так:

./src/components/UI/integrationBuilder/layoutElements/transformer/modules/ifModules/ifModule.js
  Line 103:  React Hook useEffect has missing dependencies: 'duplicateIndexes.length', 'setIsValid', and 'transformations'. Either include them or remove the dependency array  react-hooks/exhaustive-deps

Мой вопрос: как я могу сохранить ту же логику, не получая этого предупреждения?

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
7
0
6 757
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Так как при изменении состояния вы вызовете эффект. преобразования и дубликаты индексов уже будут рассмотрены. Чтобы избежать предупреждения, вы можете переместить destructure внутри useEffect

const { setIsValid } = props;

const [state, setState] = useState({
  transformations: [],
  duplicateIndexes: []
});



useEffect(() => {
  const { transformations, duplicateIndexes } = state;
  const invalids = transformations.find(x => (x.value === '' || x.replaceWith === ''));
  const hasDuplicates = duplicateIndexes.length > 0;
  const isValid = ((invalids === undefined) && (transformations.length > 0) && !hasDuplicates);

  setIsValid(isValid)

  console.info('got triggered');
}, [state]);

Кроме того, рассматривая setIsValid как зависимость от useEffect, вы не должны этого делать, поскольку новая функция для него создается при каждом рендеринге, и это приведет к тому, что useEffect будет запускаться снова и снова, если вы немного не реорганизуете свой код.

const setIsValid = useCallback((bool) => {
  setState(prev =>  Object.assign({}, prev, {isValid: bool});
}, []);

и теперь вы можете установить setIsValid в качестве зависимости.

Спасибо за быстрый ответ. Это правильно, но у меня все еще есть проблема с реквизитом setIsValid, так как он все еще требует это как зависимость. Любые идеи, как я могу обойти это?

Emre 11.06.2019 14:57

Обновлен мой ответ

Shubham Khatri 11.06.2019 20:00

Вы также можете добавить props.setIsValid в качестве зависимости напрямую, без деструктурирования.

Avin Kavish 11.06.2019 20:04

Другие вопросы по теме