How to fix useCallback received a final argument of type `object` instead of an array in React
This error occurs when useCallback receives a non-array value as its second argument instead of a dependency array. The dependencies parameter must always be an array, even if empty.
Quick fix
Fixes useCallback received a final argument of type `object` instead of an array
// ❌ Wrong - passing an object
const callback = useCallback(() => {
// function code
}, { dependency: value });
// ❌ Wrong - passing a boolean
const callback = useCallback(() => {
// function code
}, true);
// ❌ Wrong - missing brackets
const callback = useCallback(() => {
// function code
}, dependency);- Locate the problematic useCallback call
- Replace the second argument with an array
- Identify all dependencies for the callback
- Enable ESLint exhaustive-deps rule
// ❌ Wrong - passing an objectconst callback = useCallback(() => {// function code}, { dependency: value });// ❌ Wrong - passing a booleanconst callback = useCallback(() => {// function code}, true);// ❌ Wrong - missing bracketsconst callback = useCallback(() => {// function code}, dependency);useCallback received a final argument of type `object` instead of an array
What this error means
The "useCallback received a final argument of type X instead of an array" error in React occurs when the useCallback hook receives an invalid type for its second argument. The useCallback hook expects exactly two parameters: a callback function and a dependencies array. When you pass a non-array value (like an object, boolean, number, or string) as the second argument, React throws this error. The dependencies array is critical to how useCallback works. React uses this array to determine when to return a new function reference versus the memoized version from the previous render. The array should contain all reactive values (props, state, variables) that are referenced inside the callback function. If the dependency array is omitted or replaced with a non-array value, useCallback cannot perform its memoization correctly. This error typically happens due to simple syntax mistakes, such as accidentally passing an object instead of wrapping values in an array, or confusing useCallback's signature with other hooks that might accept different parameter types.
Typical symptoms
- React application throws "useCallback received a final argument of type X instead of an array" error at runtime
- useCallback hook causes component to crash during render
- TypeScript shows type error on useCallback second parameter
- ESLint warnings about incorrect useCallback usage
- Callback function behavior is unpredictable or causes infinite re-renders
- Console displays error pointing to specific useCallback invocation
- Component fails to mount or update properly when using affected callback
Common causes
- Passing an object literal as the second argument to useCallback instead of an array
- Passing a boolean value (true or false) as the second argument
- Accidentally omitting the square brackets around dependencies
- Confusing useCallback syntax with other functions that accept objects
- Passing a single dependency value directly instead of wrapping it in an array
- Using incorrect JavaScript syntax like useCallback(fn, dep1, dep2) instead of useCallback(fn, [dep1, dep2])
- Copy-pasting code with incorrect hook signatures
- Attempting to pass configuration options as a second parameter instead of dependencies
How to fix "useCallback received a final argument of type `object` instead of an array"
Check your error stack trace to find the exact component and line where the error occurs. The error message will typically point to the specific useCallback invocation that's receiving an invalid argument.
Look for patterns like:
// ❌ Wrong - passing an object
const callback = useCallback(() => {
// function code
}, { dependency: value });
// ❌ Wrong - passing a boolean
const callback = useCallback(() => {
// function code
}, true);
// ❌ Wrong - missing brackets
const callback = useCallback(() => {
// function code
}, dependency);Ensure the second parameter to useCallback is always an array, even if it's empty:
// ✅ Correct - empty array
const callback = useCallback(() => {
// function code
}, []);
// ✅ Correct - array with dependencies
const callback = useCallback(() => {
console.log(value);
}, [value]);
// ✅ Correct - multiple dependencies
const callback = useCallback(() => {
doSomething(prop1, prop2);
}, [prop1, prop2]);If your callback doesn't depend on any reactive values, use an empty array [].
Review the callback function body and list all reactive values it references. Include:
- Props used inside the callback
- State variables accessed in the callback
- Context values
- Variables declared in the component body
- Other functions defined in the component
function MyComponent({ userId, onComplete }) {
const [count, setCount] = useState(0);
const apiUrl = '/api/users';
// All reactive values must be in the dependency array
const handleSubmit = useCallback(() => {
fetch(`${apiUrl}/${userId}`)
.then(() => {
setCount(c => c + 1); // setCount is stable, doesn't need to be included
onComplete();
});
}, [userId, onComplete, apiUrl]); // Include all referenced values
return <button onClick={handleSubmit}>Submit</button>;
}Install and configure the React hooks ESLint plugin to catch dependency errors automatically:
npm install eslint-plugin-react-hooks --save-devAdd to your .eslintrc.js:
module.exports = {
plugins: ['react-hooks'],
rules: {
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'warn'
}
};The exhaustive-deps rule will warn you when dependencies are missing or specified incorrectly, preventing this type of error.
After fixing the dependency array, verify that:
1. The component renders without errors
2. The callback executes correctly when invoked
3. The callback updates when dependencies change
4. No unnecessary re-renders occur
import { useCallback, useState } from 'react';
function TestComponent() {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
console.log('Current count:', count);
setCount(count + 1);
}, [count]); // Callback will update when count changes
return (
<div>
<p>Count: {count}</p>
<button onClick={handleClick}>Increment</button>
</div>
);
}Test edge cases like rapid clicks, prop changes, and unmounting to ensure stability.
Evaluate whether memoization is actually needed. useCallback has overhead and should only be used when:
1. Passing callbacks to optimized child components that use React.memo:
const MemoizedChild = React.memo(ChildComponent);
function Parent() {
const handleClick = useCallback(() => {
// Without useCallback, MemoizedChild re-renders unnecessarily
}, []);
return <MemoizedChild onClick={handleClick} />;
}2. Callback is a dependency of other hooks:
const fetchData = useCallback(() => {
return fetch('/api/data');
}, []);
useEffect(() => {
fetchData(); // Stable reference prevents effect from running repeatedly
}, [fetchData]);If neither applies, a regular function may be simpler and more performant.
Advanced notes
TypeScript Integration: When using TypeScript, the type signature of useCallback enforces the array requirement at compile time. If you see this runtime error in a TypeScript project, it suggests the type checking may be bypassed (using 'any' types) or the error occurs in JavaScript files.
Performance Considerations: While useCallback prevents function recreation, it doesn't prevent the function from being called. If your callback contains expensive computations, consider using useMemo to cache the computation results instead of just the function reference.
Dependency Array Gotchas: Object and array dependencies are compared by reference, not value. If you pass an object literal or array literal as a dependency, it will be considered different on every render:
// ❌ Wrong - object literal creates new reference each render
const callback = useCallback(() => {
console.log(config);
}, [{ setting: true }]); // Always creates new callback
// ✅ Correct - stable reference
const config = useMemo(() => ({ setting: true }), []);
const callback = useCallback(() => {
console.log(config);
}, [config]); // Only updates when config reference changesReact 19 and Beyond: Future versions of React may introduce automatic dependency inference through the React Compiler, which could eliminate the need for manual dependency arrays. The useEffectEvent proposal (experimental) may also provide an alternative for callbacks that don't need dependency tracking.
Common Mistake with Conditional Logic: Don't conditionally create useCallback hooks. All hooks must be called in the same order on every render:
// ❌ Wrong - conditional hook
if (condition) {
const callback = useCallback(() => {}, []);
}
// ✅ Correct - hook always called, logic inside is conditional
const callback = useCallback(() => {
if (condition) {
// conditional logic here
}
}, [condition]);Frequently asked questions
- What does "useCallback received a final argument of type `object` instead of an a" mean?
- The "useCallback received a final argument of type X instead of an array" error in React occurs when the useCallback hook receives an invalid type for its second argument. The useCallback hook expects exactly two parameters: a callback function and a dependencies array. When you pass a non-array value (like an object, boolean, number, or string) as the second argument, React throws this error.
- How do I fix "useCallback received a final argument of type `object` instead of an a"?
- This error occurs when useCallback receives a non-array value as its second argument instead of a dependency array. The dependencies parameter must always be an array, even if empty.
- What causes "useCallback received a final argument of type `object` instead of an a"?
- Passing an object literal as the second argument to useCallback instead of an array Passing a boolean value (true or false) as the second argument Accidentally omitting the square brackets around dependencies
- Is the "useCallback received a final argument of type `object` instead of an a" 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: useCallback Reference(Official Docs)
- 💬GitHub Issue: useCallback received a final argument(Stack Overflow)
- 💬GitHub: React Hook useCallback has a missing dependency(Stack Overflow)
- 📖React Legacy Docs: Hooks API Reference(Official Docs)