Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

useEffect dependency array and ESLint exhaustive-deps rule

Tags:

I have a component that looks like this:

const MyComponent = props => {   const { checked, onChange, id } = props;   const [isChecked, setChecked] = useState(false);    useEffect(() => {     onChange && onChange({ isChecked: !!checked, id });     setChecked(checked);   }, [checked]);    const childProps = {     id,     isChecked   };    return <ChildComponent {...childProps} />; }; 

The exhaustive-deps lint rule isn't happy:

React Hook useEffect has missing dependencies: id and onChange. Either include them or remove the dependency array. (react-hooks/exhaustive-deps)eslint

I know that id and onChange are not going to change, so adding them to the dependency array seems unnecessary. But the rule isn't a warning, it's a clear instruction to do something.

Is the ESLint rule:

1) Over-cautious and a bit dumb in this instance, so safe to ignore?

2) Highlighting best practice - i.e. to minimise unexpected bugs that might occur in future if, for instance, changes in parent components mean that id will change at some point in future?

3) Showing an actual/possible problem with the code as it currently is?

like image 826
Will Jenkins Avatar asked Jul 10 '19 14:07

Will Jenkins


People also ask

How do you fix React hooks exhaustive DEPS?

The "react-hooks/exhaustive-deps" rule warns us when we have a missing dependency in an effect hook. To get rid of the warning, move the function or variable declaration inside of the useEffect hook, memoize arrays and objects that change on every render or disable the rule.

Can useEffect dependency be an array?

The useEffect hook allows you to perform side effects in a functional component. There is a dependency array to control when the effect should run. It runs when the component is mounted and when it is re-rendered while a dependency of the useEffect has changed.

What is useEffect DEPS?

useEffect(callback, dependencies) is the hook that manages the side-effects in functional components. callback argument is a function to put the side-effect logic. dependencies is a list of dependencies of your side-effect: being props or state values.

Does useEffect with dependency array run on first render?

Side Effect Runs After Every Render The first is the default case. If you do not pass the dependency array to the useEffect hook, the callback function executes on every render. Thus React will run the side effect defined in it after every render.


2 Answers

Actually the rule is very straightforward: Either pass an array containing all dependencies, or don't pass anything. So I guess the rule isn't dumb, it just doesn't know if the dependencies are going to change or not. So yes, if you are passing an array of dependencies it should contain ALL dependencies, including those you know for a fact that will not change. Something like this will throw a warning:

useEffect(() => dispatch({ someAction }), []) 

And to fix this you should pass dispatch as a dependency, even though it will never change:

useEffect(() => dispatch({ someAction }), [dispatch]) 

Don't disable the exhaustive deps rule, as mentioned here


UPDATE 05/04/2021

As addressed here. This is no longer necessary since eslint pull #1950.

Now referential types with stable signature such as those provenients from useState or useDispatch can safely be used inside an effect without triggering exhaustive-deps even when coming from props

like image 150
Dupocas Avatar answered Oct 06 '22 01:10

Dupocas


The way to look at it is every render has its own effect. If the effect will be the same with a particular set of values, then we can tell React about those values in the dependencies array. Ideally, a component with the same state and props, will always have the same output (rendered component + effect) after its render and effect is done. This is what makes it more resilient to bugs.

The point of the rule is that, if the deps DO change, the effect SHOULD run again, because it is now a different effect.

These 3 links also give more insights about this:

  • https://github.com/facebook/react/issues/14920#issuecomment-471070149
  • https://overreacted.io/a-complete-guide-to-useeffect/
  • https://overreacted.io/writing-resilient-components/
like image 30
Jackyef Avatar answered Oct 06 '22 03:10

Jackyef