8

Here's some sample code I've written that works fine:

useEffect(() => {
  if (!rolesIsLoading && rolesStatus === 200) {
    customer.roles = rolesData.roles;
  }
}, [rolesIsLoading, rolesStatus]);

I'm getting this warning in the console:

React Hook useEffect has missing dependencies: 'customer.roles' and 'rolesData.roles'. Either include them or remove the dependency array react-hooks/exhaustive-deps

The thing is, the code works fine now and, in some cases, when I add such dependencies, as instructed, I end up with an endless loop or some other problem.

I'd appreciate any advice you might have as to how you resolved this when you've encountered a similar situation.

robertwerner_sf
  • 1,091
  • 4
  • 21
  • 35
  • 1
    What are `customer` and `rolesData`? State variables? Something else? Please include some more code. – Chris Sep 17 '19 at 19:43

1 Answers1

12

From React DOCS:

Conditionally firing an effect

The default behavior for effects is to fire the effect after every completed render. That way an effect is always recreated if one of its dependencies changes.

However, this may be overkill in some cases, like the subscription example from the previous section. We don’t need to create a new subscription on every update, only if the source props has changed.

To implement this, pass a second argument to useEffect that is the array of values that the effect depends on. Our updated example now looks like this:

useEffect(
 () => {
   const subscription = props.source.subscribe();
   return () => {
     subscription.unsubscribe();
   };
 },
 [props.source],
);

So, from the exercpt above we see that the dependencies array serves the purpose to conditionally fire an effect.

That warning you're getting is because you're using some external (from the effect's perspective) variables in your effect function that you're not mentioning in the dependency array.

React is worried that you might be getting new values for those variables in future renders, and since your effect uses them, React "default intent" is to re-run that effect with the new variables values. So your effect would always be up to date.

So you need to think if you want to re-run your effect if/when those variables change in the future.

Basic recommendations:

  • Add them to the dependency array
  • If they never change, there will be no difference
  • If they change, add some conditionals to your effect to decide whether you should do something based on the new variables values or not
  • If they're changing only in reference, but not in value (like functions, arrays, objects, etc), you can use the useCallback or useRef hook to preserve the "reference" for those variables from the first render and not get new references on every render.
cbdeveloper
  • 27,898
  • 37
  • 155
  • 336
  • Thank you for this! And I definitely need to investigate `useCallback` deeper. Using it may be the key when I add all dependencies and then undesirable things happen to my previously working `useEffect` code. – robertwerner_sf Sep 18 '19 at 20:31