Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setstate in React's useEffect dependecy array

What's the idea behind defining the setState values inside useEffect's dependency array?

const [someState, setSomeState] = useState();
...
useEffect(() => {
  // Do something
  setSomeState('some value');
}, [setSomeState]);

React Hook useEffect has a missing dependency: 'setSomeState'.
Either include it or remove the dependency array.
eslint(react-hooks/exhaustive-deps)

Not exactly sure if this example would cause eslint to ask to define setSomeState in the dependency array, but I have seen this kind of moments when writing with useEffect. What is React listening to in this case? My understanding is that useEffect listens for changes in the values in the dependency array, but would setSomeState ever change? What am I missing here?

like image 876
Joseph K. Avatar asked Jan 13 '20 00:01

Joseph K.


1 Answers

In this case, no, the useState setter function will never change, but useEffect doesn't know it is a function from another hook, it just sees a function.

Consider this use case:

const MyComponent = ({ onUpdate }) => {
  const [state, setState] = useState();
  useEffect(() => {
    // state updated, call onUpdate callback with state
    onUpdate(state);
  }, [onUpdate, state]);
  return ...
}

Now parent component can, given

<MyComponent onUpdate={onUpdateHandler} />

define onUpdateHandler as

let onUpdateHandler = console.log;

then later change it while still mounted

onUpdateHandler = state => dispatch({ type: 'SAVE_STATE', state });

By placing the callback in the dependency array the effect hook see the value of onUpdate changed and trigger the effect again. If it didn't include the callback then it would continue to console.log state updates instead of now handling it differently.

It is more likely for values to change than it is for functions to change, but function values can change. You likely have an eslinter that is recommending you add all the variables used within the hook to the dependency array, and this will in most cases be the correct thing to do. A few exceptions are for example, when you want an effect to compute ONLY when the component mounts by specifying an empty array, or not including some variables that are functions that you KNOW will never change during the life of the component, and in these cases you can use the eslint-disable-next-line react-hooks/exhaustive-deps override to unflag it as a warning. Caution though, as this will disable the linting checks so it is possible for bugs to creep in if not paying attention.

like image 146
Drew Reese Avatar answered Sep 22 '22 06:09

Drew Reese