Looking at the docs, there is a note at the bottom of this section [edited link] that makes it seem like only props or state should be used in a hook dependency list. However, when a "complex expression" on props or state is used in the list, the eslint plugin gives the following:
React Hook useEffect has a complex expression in the dependency array. Extract it to a separate variable so it can be statically checked. eslint(react-hooks/exhaustive-deps)
This has me thinking about what is allowed to be used as a dependency. Can we use a local variable that is calculated from props? Do we need to create some sort of new state variable or ref in this case? I'm not certain if hooks are executed in place within the component (so local variables are available) or are hoisted out of the context of the render (so we have to use only state, props, or other hook values like refs/memos).
A component has a prop, data, that is an object.
data: {
name: 'name',
id: 2
}
1) It looks like data.name
can be used in the dependencies. But can we use a local variable that is set to the property?
const { name } = data;
useEffect(fn, [name]);
2) Would we be able to use a variable that is calculated by a prop in a dependency array?
const isOdd = Boolean(data.id % 2);
useEffect(fn, [isOdd]);
Both cases seem to work with small tests. I'm not knowledgable enough with Hooks to know if it's breaking some rules that would leave the results as indeterminate.
November 29, 2021 4 min read. Dependency injection (DI) is a pattern where components necessary for your code to run are hot-swappable. This means that your dependencies are not hard-coded in your implementation and can change as your environment changes.
There are 3 rules for hooks: Hooks can only be called inside React function components. Hooks can only be called at the top level of a component. Hooks cannot be conditional.
Functions in a dependency arrayIf we call functions inside the useEffect callback function, we would have to include the function name in the dependency array. This will result in a bug as printName() isn't wrapped in the callback. That will lead to useEffect triggering on every render of React component!
Useeffect dependency array: TL;DR You should use react-hooks/exhaustive-deps eslint rule and refactor your code in this order: Think about if the useEffect is useful or if it should be refactored. Declare the function in the useEffect when it is used only in the useEffect.
Optimizing Performance by Skipping Effects may help understanding hook dependencies.
Note
If you use this optimization, make sure the array includes all values from the component scope (such as props and state) that change over time and that are used by the effect. Otherwise, your code will reference stale values from previous renders. Learn more about how to deal with functions and what to do when the array changes too often.
The important bit, "...all values from the component scope...", meaning any value within the component scope used within the hook.
Q: Can we use a local variable that is calculated from props?
Q: Do we need to create some sort of new state variable or ref in this case?
Q: I'm not certain if hooks are executed in place within the component (so local variables are available) or are hoisted out of the context of the render (so we have to use only state, props, or other hook values like refs/memos)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With