Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determine which dependency array variable caused useEffect hook to fire

Is there an easy way to determine which variable in a useEffect's dependency array triggers a function re-fire?

Simply logging out each variable can be misleading, if a is a function and b is an object they may appear the same when logged but actually be different and causing useEffect fires.

For example:

React.useEffect(() => {   // which variable triggered this re-fire?   console.log('---useEffect---') }, [a, b, c, d]) 

My current method has been removing dependency variables one by one until I notice the behavior that causes excessive useEffect calls, but there must be a better way to narrow this down.

like image 806
Cumulo Nimbus Avatar asked Mar 15 '19 17:03

Cumulo Nimbus


People also ask

What triggers 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.

What is the dependencies array in the useEffect hook?

Dependency arrays are a concept that is tightly coupled to hooks in React (thus also to function components). Some hooks, like useEffect and useCallback have 2 arguments. The first one is a callback (a function), and the second one is the dependency array. It takes the form of an array of variables.

Does useEffect fire on Mount?

Important: the useEffect hook will always run on mount regardless of if there is anything in its dependency array. We probably don't want to actually run this effect on our data when it's undefined (as it will be on initial render) but rather we want to wait until it is populated from the API call.

How do I fix React hook useEffect has missing dependencies?

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.


1 Answers

I ended up taking a little bit from various answers to make my own hook for this. I wanted the ability to just drop something in place of useEffect for quickly debugging what dependency was triggering useEffect.

const usePrevious = (value, initialValue) => {   const ref = useRef(initialValue);   useEffect(() => {     ref.current = value;   });   return ref.current; }; 
const useEffectDebugger = (effectHook, dependencies, dependencyNames = []) => {   const previousDeps = usePrevious(dependencies, []);    const changedDeps = dependencies.reduce((accum, dependency, index) => {     if (dependency !== previousDeps[index]) {       const keyName = dependencyNames[index] || index;       return {         ...accum,         [keyName]: {           before: previousDeps[index],           after: dependency         }       };     }      return accum;   }, {});    if (Object.keys(changedDeps).length) {     console.log('[use-effect-debugger] ', changedDeps);   }    useEffect(effectHook, dependencies); }; 

Below are two examples. For each example, I assume that dep2 changes from 'foo' to 'bar'. Example 1 shows the output without passing dependencyNames and Example 2 shows an example with dependencyNames.

Example 1

Before:

useEffect(() => {   // useEffect code here...  }, [dep1, dep2]) 

After:

useEffectDebugger(() => {   // useEffect code here...  }, [dep1, dep2]) 

Console output:

{   1: {     before: 'foo',     after: 'bar'   } } 

The object key '1' represents the index of the dependency that changed. Here, dep1 changed and is the 2nd item in the dependency, or index 1

Example 2

Before:

useEffect(() => {   // useEffect code here...  }, [dep1, dep2]) 

After:

useEffectDebugger(() => {   // useEffect code here...  }, [dep1, dep2], ['dep1', 'dep2']) 

Console output:

{   dep2: {     before: 'foo',     after: 'bar'   } } 
like image 113
Bradley Avatar answered Sep 17 '22 15:09

Bradley