React issues this warning when the second argument to useEffect is an object (or any non-array value) instead of a dependency array.
React expects the last argument passed to useEffect to be an array of dependencies that control when the effect re-runs. When you pass an object (or any other non-array value) React cannot compare the dependencies between renders, so it throws this warning because the hook signature was violated. The mistake usually looks like passing configuration objects, props, or state values directly instead of wrapping them in square brackets. Even though objects are technically reference types in JavaScript, useEffect needs an array specifically so React can inspect each dependency with Object.is. Without that array, React cannot determine when to skip or re-run the effect, which can lead to inconsistent behavior or infinite loops in development builds.
Read the console warning to see which hook call triggered the message. The stack trace usually points to a component file and line number, and the warning text shows the value passed to useEffect.
Look for code such as:
useEffect(() => {
fetchData();
}, { userId }); // ❌ object instead of array
useEffect(() => {
console.log(props);
}, props); // ❌ passing props directly instead of [props]Any non-array second argument is invalid and will trigger the warning.
Change the second argument to square brackets and list every value from the component scope that the effect relies on.
// ✔️ empty dependency array runs only once
useEffect(() => {
sendAnalytics();
}, []);
// ✔️ array with dependencies
useEffect(() => {
fetchData(userId);
}, [userId]);
// ✔️ multiple dependencies
useEffect(() => {
updateChart(data, theme);
}, [data, theme]);If you actually want the effect to run on every render, simply omit the second parameter entirely instead of passing an object.
Objects and arrays are reference types, so creating a new object inside render produces a new reference on every render even if the content does not change. Instead of listing the raw object as a dependency, either memoize it with the primitive values it depends on (useMemo with those primitives) or destructure those primitives directly and list them individually (for example, [filters.status, filters.sort]).
This keeps useEffect happy and avoids passing an object directly, because React compares each dependency with Object.is and will re-run the effect whenever a reference changes.
Add eslint-plugin-react-hooks if it is missing so you catch dependency array mistakes automatically.
npm install eslint-plugin-react-hooks --save-devIn your ESLint config:
{
"plugins": ["react-hooks"],
"rules": {
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn"
}
}The exhaustive-deps rule enforces that the second argument is an array and that it lists the right values, preventing this warning before you even run the app.
Run the app locally and observe the console to make sure the warning disappears. Reload the component with the relevant props/state so the effect runs and confirm:
- The warning no longer appears.
- The effect only runs when listed dependencies change.
- Child components no longer re-render unnecessarily.
npm run dev
# or
npm startUse React DevTools to inspect renders if you still suspect unnecessary executions.
How React compares dependencies: React uses Object.is internally to compare array entries between renders. That comparison only works when you provide an array. Passing an object bypasses this mechanism and leaves React guessing, which prompts the warning.
Avoid over-optimizing: Don't try to satisfy this warning by wrapping non-array values in helper functions that still return objects. The fix is always to use an array; if you need to depend on derived values, memoize them or break them into primitives before listing them as dependencies.
React Hook useCallback has a missing dependency: 'variable'. Either include it or remove the dependency array react-hooks/exhaustive-deps
React Hook useCallback has a missing dependency
Cannot use private fields in class components without TS support
Cannot use private fields in class components without TS support
Cannot destructure property 'xxx' of 'undefined'
Cannot destructure property of undefined when accessing props
useNavigate() may be used only in the context of a <Router> component.
useNavigate() may be used only in the context of a Router component
Cannot find module or its corresponding type declarations
How to fix "Cannot find module or type declarations" in Vite