简体   繁体   中英

Adding exhaustive dependencies into useEffect and useCallback causes infinite loop

So I thought I was getting the hang of these hooks, but the lint rule react-hooks/exhaustive-deps is tripping me up.

I have this method inside my Provider

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

I'm allowing the rest of my app to access this by passing it into the value prop...

return <Provider value={{onScreenChange, ... }}>children</Provider>

And then I'm calling this method from a child component when the route changes

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

The above code works exactly how I want, and I can't see this causing any bugs. However eslint is telling me:

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

When I add screenState into the array, it causes an infinite loop as soon as the onScreenChange method is called.

It's pretty obvious why the loop is now happening, but how do I stop this and "follow the rules"?

Thanks in advance for any help!

The warning from eslint seems to be correct. Since screenState value won't be updated correctly if the onScreenChange method is called multiple times. You must provide screenState as a depedency to useCallback

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

The other way to write the same code without adding the deps is to make use of state updater callback pattern

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


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

However you may choose to disable the deps warning if you are absolutely sure what you are trying to do is correct.

You may read below post for more inforamtion:

How do I fix missing dependency in React Hook useEffect

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM