There is no warning when I add prop.value
to DependencyList.
But there is one warning when I add prop.func
to DependencyList
React Hook useEffect has a missing dependency: 'prop'. Either include it or remove the dependency array. (react-hooks/exhaustive-deps)
Seems variables and functions are different in DependencyList, why is that? Should I add prop
to DependencyList in both useEffect
?
function Box(prop) {
useEffect(() => {
console.log(prop.value);
}, [prop.value]);
useEffect(() => {
prop.func();
}, [prop.func]);
//^ React Hook useEffect has a missing dependency: 'prop'. Either include it or remove the dependency array. (react-hooks/exhaustive-deps)
return <div></div>;
}
function App() {
return (
<Box
func={() => {
console.log("function");
}}
value={"value"}
></Box>
);
}
https://codesandbox.io/s/react-useeffect-issue-6m5kxg?file=/src/index.js
2
Answers
The linter complains because
prop.func()
is a method call that runs the function in the context of theprop
object. ConsiderThis will log
"value"
, and presumably should log again whenprop.value
changes not just whenprop.func
changes. You can fix this by not using method syntax in the effect:or
or
In React, the useEffect hook is used to handle side effects in functional components. It takes a function as its first argument and an array of dependencies as its second argument. The dependencies array is used to specify which values the effect depends on. When any of the dependencies change, the effect will be re-run.
In your example, you have two useEffect hooks in the Box component:
useEffect with dependency [prop.value]: This means the effect depends on the value of prop.value. When prop.value changes, the effect will be triggered.
useEffect with dependency [prop.func]: This means the effect depends on the function prop.func. When prop.func changes (if it is a new reference), the effect will be triggered.
The difference between the two is how React checks for changes in the dependencies. For primitive values like prop.value (strings, numbers, etc.), React can easily determine if the value has changed by a simple comparison. However, for objects or functions like prop.func, React checks for a change in the reference. If the reference to the function changes (i.e., you pass a new function each render), React considers it a different function, even if the implementation is the same. This is why you get the warning in the second useEffect.
To address the warning, you have a few options:
Ignore the warning: If you are certain that prop.func will never change during the component’s lifecycle, and it doesn’t depend on any other state or prop, you can safely ignore the warning. But be careful with this approach, as it might cause bugs in the future if prop.func changes unexpectedly.
Include prop in the dependency list for the second useEffect: If prop is expected to change and prop.func depends on some other property of prop, you should include prop in the dependency list of the second useEffect. This way, when prop changes, the effect will be triggered and will use the latest prop.func. However, adding the entire prop object to the dependency list might lead to unnecessary re-renders if other properties of prop change but don’t affect prop.func.
Extract prop.func outside the component: If prop.func doesn’t depend on any component state or props and doesn’t change during the component’s lifecycle, you can extract it outside the component so that it doesn’t change between renders. This way, you can safely exclude prop.func from the dependency list.