Реагируйте на хук useEffect и предупреждение eslint

#reactjs #react-hooks #use-effect

Вопрос:

Я ищу рекомендации о том, как решить следующую проблему:

У меня есть компонент A, который имеет два состояния, состояние 1 и состояние 2.

Если я хочу запускать эффект только при изменении состояния 1, но в обратном вызове useEffect я использую значение состояния 2, как я могу решить проблему с предупреждением о зависимостях массива eslint react hooks ?

Экс.

 function A() {  const [state1, setState1] = useState(0);  const [state2, setState2] = useState(0);   useEffect(() =gt; {  const a = state1   state2;  // do some async logic using a    }, [state1]); //Here eslint react hooks rule requests adding state2 to the dependency array!  return lt;divgt; some text lt;/divgt;  }  

Ответ №1:

Обычно распространенным методом было бы отключить правило компоновки специально для этой строки.

 function A() {  const [state1, setState1] = useState(0);  const [state2, setState2] = useState(0);   useEffect(() =gt; {  // do some async logic using a  const a = state1   state2;   // eslint-disable-next-line react-hooks/exhaustive-deps  }, [state1]);   return lt;divgt; some text lt;/divgt;; }  

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

Вы можете использовать ссылку React и дополнительный useEffect крюк для кэширования текущего state2 значения и ссылаться на это в другом useEffect обратном вызове.

 function A() {  const [state1, setState1] = useState(0);  const [state2, setState2] = useState(0);   const state2Ref = useRef(state2);   useEffect(() =gt; {  state2Ref.current = state2;  }, [state2]);   useEffect(() =gt; {  // do some async logic using a  const a = state1   state2Ref.current;  }, [state1]);   return (  ...  ); }  
 function A() {  const [state1, setState1] = React.useState(0);  const [state2, setState2] = React.useState(0);   const state2Ref = React.useRef(state2);   React.useEffect(() =gt; {  state2Ref.current = state2;  }, [state2]);   React.useEffect(() =gt; {  // do some async logic using a  const a = state1   state2Ref.current;  console.log("effect called", a);  }, [state1]);   return (  lt;divgt;  some text  lt;divgt;  lt;button type="button" onClick={() =gt; setState1((c) =gt; c   1)}gt;  Update State 1  lt;/buttongt;  lt;button type="button" onClick={() =gt; setState2((c) =gt; c   1)}gt;  Update State 2  lt;/buttongt;  lt;/divgt;  lt;/divgt;  ); }  const rootElement = document.getElementById("root"); ReactDOM.render(  lt;A /gt;,  rootElement ); 
 lt;script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"gt;lt;/scriptgt; lt;script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"gt;lt;/scriptgt; lt;div id="root" /gt; 

Ответ №2:

Вам нужно добавить // eslint-disable-next-line react-hooks/exhaustive-deps в свой пользовательский эффект вот так:

 function A() {  const [state1, setState1] = useState(0);  const [state2, setState2] = useState(0);   useEffect(() =gt; {  const a = state1   state2;  // do some async logic using a    // eslint-disable-next-line react-hooks/exhaustive-deps  }, [state1]); //Here eslint react hooks rule requests adding state2 to the dependency array!   return lt;divgt; some text lt;/divgt;  }  

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

1. Спасибо @Luccin, но я ищу более продвинутый способ, не отключая это правило. Например, я подумал о создании новой ссылки, которая содержит обновленное значение state2…