将详尽的依赖项添加到 useEffect 和 useCallback 会导致无限循环

Dan*_*anV 5 javascript reactjs react-hooks

所以我以为我已经掌握了这些钩子的窍门,但是 lint 规则react-hooks/exhaustive-deps让我绊倒了。

我的Provider 中有这个方法

const onScreenChange = useCallback(
(key, value) => {
  const newState = Object.assign({}, screenState, { [key]: value });
  localStorage.setItem('screens', JSON.stringify(newState));
  setScreenState(newState);
},
[]); // screenState
Run Code Online (Sandbox Code Playgroud)

我允许我的应用程序的其余部分通过将它传递到 value 属性来访问它......

return <Provider value={{onScreenChange, ... }}>children</Provider>
Run Code Online (Sandbox Code Playgroud)

然后当路由改变时我从子组件调用这个方法

useEffect(() => {
   if (match.path === `/${screenKey}`) {
     onScreenChange(screenKey, 'external');
   }
}, [onScreenChange, match.path, screenKey]);
Run Code Online (Sandbox Code Playgroud)

上面的代码完全按照我的要求工作,我看不到这会导致任何错误。然而 eslint 告诉我:

React Hook useCallback has a missing dependency: 'screenState'. Either include it or remove the dependency array

当我添加screenState到数组中时,只要onScreenChange调用该方法,它就会导致无限循环。

很明显为什么现在正在发生循环,但是我该如何停止并“遵守规则”?

在此先感谢您的帮助!

Shu*_*tri 4

eslint 的警告似乎是正确的。onScreenChange由于如果多次调用该方法, screenState 值将无法正确更新。您必须提供screenState作为依赖项useCallback

const onScreenChange = useCallback(
(key, value) => {
  const newState = Object.assign({}, screenState, { [key]: value });
  localStorage.setItem('screens', JSON.stringify(newState));
  setScreenState(newState);
},
[screenState]); 
Run Code Online (Sandbox Code Playgroud)

在不添加依赖项的情况下编写相同代码的另一种方法是利用状态更新器回调模式

const onScreenChange = useCallback(
(key, value) => {


  setScreenState(oldState => {
       const newState = Object.assign({}, oldState, { [key]: value });
       localStorage.setItem('screens', JSON.stringify(newState));
       return newState;
  });
},
[]); 
Run Code Online (Sandbox Code Playgroud)

但是,如果您绝对确定自己尝试执行的操作是正确的,则可以选择禁用 deps 警告。

您可以阅读以下帖子以获取更多信息:

如何修复 React Hook useEffect 中缺少的依赖项