Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Correct/Incorrect to ignore some React useEffect dependency warnings?

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.

like image 722
robertwerner_sf Avatar asked Sep 17 '19 19:09

robertwerner_sf


People also ask

How do you fix missing dependency warning when using useEffect React?

The warning "React Hook useEffect has a missing dependency" occurs when the useEffect hook makes use of a variable or function that we haven't included in its dependencies array. To solve the error, disable the rule for a line or move the variable inside the useEffect hook.

What happens if we don't pass dependency array in useEffect?

So what happens when the dependency array is empty? It simply means that the hook will only trigger once when the component is first rendered. So for example, for useEffect it means the callback will run once at the beginning of the lifecycle of the component and never again.

Can we use useEffect without dependency?

It runs when the component is mounted and when it is re-rendered while a dependency of the useEffect has changed. This is powerful, but it is easy to omit dependencies and create bugs in your app.

What is triggering useEffect?

Triggers give you the power to determine execution time In a sense, useEffect is a similar idea to a database Hook. A database Hook allows you to perform actions after a database operation. Say you're building a game, and whenever a player's score updates, you also want to update the high score if necessary.


1 Answers

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.
like image 152
cbdeveloper Avatar answered Sep 19 '22 18:09

cbdeveloper