Есть ли способ избежать бесконечного цикла зависимостей и передать правильные зависимости в useEffect hook в этом случае?

#reactjs #react-hooks

#reactjs #реагирующие крючки

Вопрос:

У меня есть пользовательский хук, который получает обратный вызов в качестве одного из аргументов и вызывает его в useEffect

 const customHook = (callback: Function) => {
  ...
  useEffect(() => {
    if (something) {
      callback();
    }
  }, [other things, callback]);

  return {values}
}
 

Проблема здесь в том, что callback это функция и вызывает useEffect запуск в цикле. ESLint предлагается useCallback в родительском компоненте. Поэтому я решил обернуть это callback в useCallback where я вызываю my customHook .

Итак, у меня было бы что-то подобное в моем компоненте:

 const memoizedCallback = useCallback(() => {
    myFunction(values);
  }, [values, myFunction]);

  const { values } = customHook(memoizedCallback);
 

И здесь у меня есть моя проблема — зависимости myFunction возвращаются, customHook и я не могу использовать их до того, как они определены. Но я также не могу поставить memoizedCallback after customHook call по тем же причинам.

И теперь я застрял в этом бесконечном цикле зависимостей, и я не уверен, как это решить, если так или иначе, не просто игнорируя предупреждение eslint.

Так что любые идеи и решения будут высоко оценены 🙂

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

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

Ответ №1:

Если изменение обратного вызова не должно приводить к useEffect выполнению блока, установите значение callback ref:

 const customHook = (callback: Function) => {
  const fn = useRef(callback);
  
  ...
  
  useEffect(() => {
    fn.current = callback;
  })
  
  useEffect(() => {
    if (something) {
      fn.current(); // fn.current?.() if fn.current might be undefined
    }
  }, [something]);

  return {values}
}
 

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

1. Это сработало! Спасибо. Интересный подход, придется запомнить это на будущее 🙂