React exhaustive-deps rule flagging missing dependencies from custom hooks

Viewed 128

Disclaimer: I searched SO and I found this question to be reeeeaaaaaally close to mine, but I did not fully understand the only answer. I added a post to ask more explanation (I cannot add comments because I lack reputation) but it was deleted as it was not an answer, hence the new thread I am forced to create here.

I need some explanation about the exhaustive-deps rule. I think I am missing something.

Thanks for your lights! :)

The React doc states that:

React guarantees that setState function identity is stable and won’t change on re-renders. This is why it’s safe to omit from the useEffect or useCallback dependency list.

(source)

However, consider this:

import { useEffect, useState } from 'react';

// Writing a custom hook that only calls `useState` and returns what `useState` returns
const useMyOwnStateHook = initialValue => useState(initialValue);

const MyComponent = () => {
  // Here we have a direct call to `useState`
  const [, setStandardState] = useState('');
  // Here we call `useState` in our hook
  const [, setMyOwnState] = useMyOwnStateHook('');

  useEffect(() => {
    // This call is safe and does not raise any linting error, as per the doc (https://reactjs.org/docs/hooks-reference.html#usestate)
    setStandardState('');
    // This call triggers the following error in the console:
    // Line 19:6:  React Hook useEffect has a missing dependency: 'setMyOwnState'. Either include it
    // or remove the dependency array  react-hooks/exhaustive-deps
    setMyOwnState('');
  }, []);
  return <span></span>
};

export default MyComponent;

Here I do not understand why the calls to setStandardState and setMyOwnState are not both safe. I have such dependencies all over my code and it really burdens the dependency arrays of my useEffects and I would love to understand how I could get rid of them :-)

I am using the following versions of React in my package.json:

"react": "^17.0.2",
"react-scripts": "4.0.3",

Thanks for your time!

1 Answers

If setMyOwnState doesn't change between renders (like a setState function), you could simply list it as a dependency, and not worry about it causing any unwanted side-effects, as it will never change.
This is how react-redux handles the same issue with their useDispatch hook

If setMyOwnState can change between renders, then it would make sense that react would warn you about it

Related