How to fix useEffect received a final argument of type `object` instead of an array in React
React issues this warning when the second argument to useEffect is an object (or any non-array value) instead of a dependency array.
Quick fix
Fixes useEffect received a final argument of type `object` instead of an array
useEffect(() => {
fetchData();
}, { userId }); // ❌ object instead of array
useEffect(() => {
console.log(props);
}, props); // ❌ passing props directly instead of [props]- Locate the offending useEffect call
- Switch the second argument to an array
- Stabilize object dependencies before adding them
- Install and configure the React Hooks ESLint plugin
useEffect(() => {fetchData();}, { userId }); // ❌ object instead of arrayuseEffect(() => {console.log(props);}, props); // ❌ passing props directly instead of [props]useEffect received a final argument of type `object` instead of an array
What this error means
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.
Typical symptoms
- Console warning that explicitly names the wrong type (object) instead of the dependency array
- Effect runs on every render or stops respecting dependencies
- Child components re-render more often than expected
- TypeScript complains that object is not assignable to DependencyList
- React DevTools highlights the component that has the bad useEffect call
- Development build shows the warning repeatedly whenever the component renders
- ESLint react-hooks/exhaustive-deps rule may still pass because lint only checks arrays
Common causes
- Passing an object literal / configuration object directly as the second argument to useEffect
- Mistaking useEffect's dependency array for setTimeout's delay argument and using curly braces
- Forgetting to wrap a single dependency value in brackets (e.g., using `useEffect(fn, props)`)
- Confusing the lint rule for exhaustive deps with the hook signature and omitting the array entirely
- Trying to reuse an object reference as a dependency without stabilizing it first
- Copy-pasting code that uses curly braces instead of square brackets for dependencies
- Passing React state setters or reducer dispatchers as the second argument
- Constructing the dependency list dynamically with helper functions that return objects instead of arrays
How to fix "useEffect received a final argument of type `object` instead of an array"
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.
Advanced notes
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.
Frequently asked questions
- What does "useEffect received a final argument of type `object` instead of an arr" mean?
- 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.
- How do I fix "useEffect received a final argument of type `object` instead of an arr"?
- React issues this warning when the second argument to useEffect is an object (or any non-array value) instead of a dependency array.
- What causes "useEffect received a final argument of type `object` instead of an arr"?
- Passing an object literal / configuration object directly as the second argument to useEffect Mistaking useEffect's dependency array for setTimeout's delay argument and using curly braces Forgetting to wrap a single dependency value in brackets (e.g., using useEffect(fn, props))
- Is the "useEffect received a final argument of type `object` instead of an arr" error serious?
- It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.
Official resources & further reading
- 📚React Official Documentation
- 📖React Docs: useEffect reference(Official Docs)
- 📖React Beta Docs: Effect Hook guide(Official Docs)