Реагирующий хук отсутствует зависимость пользовательского установщика хуков

#reactjs #typescript #eslint

#reactjs #typescript #eslint

Вопрос:

Я хорошо понимаю, что Hook has missing dependency это такое, что это значит и почему важно следить за всеми зависимостями, но это просто странно.

 export function Compo() {
  const [value, setValue] = useState<number>();

  useEffect(() => {
    setValue(Date.now());
  }, []);

  return (
    <>{value}</>
  );
}
 

работает нормально, но:

 function useValue() {
  return useState<number>();
}

export function Compo() {
  const [value, setValue] = useValue();

  useEffect(() => {
    setValue(Date.now());
  }, []);

  return (
    <>{value}</>
  );
}
 

показать хорошо известное React Hook useEffect has a missing dependency: 'setValue'. Either include it or remove the dependency array react-hooks/exhaustive-deps .

Ответ №1:

То, что вы заметили в своем примере, является причудой правила react-hooks/exhaustive-deps . Он предоставляет особые привилегии крючкам, о которых он знает, и знает, что они «стабильны» при определенных обстоятельствах.

Цитирование реализации:

 // Next we'll define a few helpers that helps us
// tell if some values don't have to be declared as deps.

// Some are known to be stable based on Hook calls.
// const [state, setState] = useState() / React.useState()
//               ^^^ true for this reference
// const [state, dispatch] = useReducer() / React.useReducer()
//               ^^^ true for this reference
// const ref = useRef()
//       ^^^ true for this reference
// False for everything else.
 

источник: https://github.com/facebook/react/blob/v17.0.1/packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.js#L152

В частности, эта часть правила, по-видимому, является тем, что освобождает установщик useState крючка в этих обстоятельствах:

 if (name === 'useState') {
  const references = resolved.references;
  for (let i = 0; i < references.length; i  ) {
    setStateCallSites.set(
      references[i].identifier,
      id.elements[0],
    );
  }
}
// Setter is stable.
return true;
 

Неудачный результат того, что хук полезен / умен, заключается в том, что он может привести к путанице, когда его вывод не работает, как в сценарии, который вы только что описали.

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

1. Я думаю, что я никогда не видел, чтобы кто-то углублялся в ответ, спасибо за усилия! Так что, по сути, мне просто нужно найти способ обойти это. Я полагаю, что правило недостаточно мощное, чтобы находить динамические ссылки с помощью пользовательских крючков. Есть идеи, как я мог бы это обойти?

2. Нет ничего плохого в том, чтобы включить установщик в массив зависимостей, это просто с достаточно глубоким выводом, который вам не понадобится . То же useState самое, вы все равно можете добавить его, не меняя поведение, просто плагин eslint достаточно «умен», чтобы знать, что он вам не нужен.