How to fix useCallback was passed a second argument as an object when an array was expected in React
This error occurs when you accidentally pass an object (using curly braces {}) instead of an array (using square brackets []) as the second argument to useCallback. React requires the dependency list to be an array, not a plain object.
Quick fix
Fixes useCallback was passed a second argument as an object when an array was expected
// WRONG - using object syntax
const memoizedCallback = useCallback(() => {
doSomething(value);
}, { value }); // ❌ Object instead of array
// WRONG - empty object
const memoizedCallback = useCallback(() => {
doSomething();
}, {}); // ❌ Empty object instead of empty array- Locate the problematic useCallback call
- Replace curly braces with square brackets
- List dependencies correctly in the array
- Handle object dependencies properly
// WRONG - using object syntaxconst memoizedCallback = useCallback(() => {doSomething(value);}, { value }); // ❌ Object instead of array// WRONG - empty objectconst memoizedCallback = useCallback(() => {doSomething();}, {}); // ❌ Empty object instead of empty arrayuseCallback was passed a second argument as an object when an array was expected
What this error means
The useCallback hook in React requires exactly two arguments: the callback function to memoize, and an array of dependencies that determines when the callback should be recreated. This error appears when you mistakenly pass a plain object `{}` instead of an array `[]` as the second parameter. While both arrays and objects are technically "objects" in JavaScript, React specifically requires the dependency list to be an array. The hook uses this array to track changes in dependencies using the Object.is comparison algorithm. When you pass an object instead of an array, React cannot properly track dependency changes, and the memoization behavior breaks. This is typically a simple syntax mistake - using curly braces when you meant to use square brackets. The fix is straightforward: replace the object notation with proper array syntax for the dependency list.
Typical symptoms
- Console warning: "useCallback was passed a second argument as an object when an array was expected"
- Callback function not memoizing correctly despite using useCallback
- Component re-renders more frequently than expected
- TypeScript error if using strict typing: "Type object is not assignable to type DependencyList"
- React DevTools shows callback function changing on every render
- Child components receiving the callback re-render unnecessarily
- Performance issues due to excessive callback recreation
Common causes
- Using curly braces {} instead of square brackets [] for the dependency array
- Confusion between object literal syntax and array syntax in JavaScript
- Copy-pasting code that incorrectly formatted the dependencies parameter
- Mistakenly trying to pass a configuration object as the second parameter
- Auto-complete or IDE suggestion inserting wrong syntax
- Mixing up useCallback syntax with other hooks that accept object parameters
- Refactoring code and accidentally changing brackets to braces
- Attempting to pass a single object dependency without wrapping it in an array
How to fix "useCallback was passed a second argument as an object when an array was expected"
Find the useCallback hook that's causing the error. Look for code that passes curly braces as the second argument:
// WRONG - using object syntax
const memoizedCallback = useCallback(() => {
doSomething(value);
}, { value }); // ❌ Object instead of array
// WRONG - empty object
const memoizedCallback = useCallback(() => {
doSomething();
}, {}); // ❌ Empty object instead of empty arrayThe error message in your console will typically point to the specific file and line number where this occurs.
Change the second argument from object notation {} to array notation []:
// CORRECT - using array syntax
const memoizedCallback = useCallback(() => {
doSomething(value);
}, [value]); // ✅ Array with dependency
// CORRECT - empty dependency array
const memoizedCallback = useCallback(() => {
doSomething();
}, []); // ✅ Empty arrayThis is the core fix - ensuring the second parameter is an array, not an object.
Include all values from component scope that the callback uses:
function MyComponent({ userId, onUpdate }) {
const [count, setCount] = useState(0);
// Include all external values the callback references
const handleClick = useCallback(() => {
console.log('User:', userId, 'Count:', count);
onUpdate(userId, count);
}, [userId, count, onUpdate]); // ✅ All dependencies listed
return <button onClick={handleClick}>Click me</button>;
}React will recreate the callback whenever any value in this dependency array changes.
If you need to depend on object values, extract specific properties or use useMemo:
// OPTION 1: Depend on specific object properties
const handleUpdate = useCallback(() => {
updateUser(user.id, user.name);
}, [user.id, user.name]); // ✅ Specific properties, not entire object
// OPTION 2: Memoize the object first
const stableConfig = useMemo(() => ({
timeout: 1000,
retries: 3
}), []); // Memoize object
const processData = useCallback(() => {
fetchData(stableConfig);
}, [stableConfig]); // ✅ Stable object referencePassing entire objects as dependencies can cause unnecessary re-renders because objects are compared by reference, not by value.
Install and configure the React Hooks ESLint plugin to catch dependency issues automatically:
npm install eslint-plugin-react-hooks --save-devAdd to your ESLint configuration:
{
"plugins": ["react-hooks"],
"rules": {
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn"
}
}The exhaustive-deps rule will warn you about missing dependencies and incorrect dependency array syntax.
Verify that your callback is now memoizing correctly:
function TestComponent() {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
console.log('Callback executed');
}, []); // Empty array - never recreated
// This ref will track callback identity
const callbackRef = useRef(handleClick);
useEffect(() => {
if (callbackRef.current !== handleClick) {
console.log('Callback changed'); // Should not log if dependencies unchanged
}
callbackRef.current = handleClick;
}, [handleClick]);
return (
<div>
<button onClick={() => setCount(count + 1)}>Re-render</button>
<ChildComponent onAction={handleClick} />
</div>
);
}The child component should not re-render when the parent re-renders if the callback is properly memoized.
Advanced notes
When to use empty dependency array: Using useCallback(() => {}, []) with an empty array means the callback is created once and never recreated. This is useful for event handlers that don't depend on component state or props, but be careful - if your callback references stale values, you'll have bugs.
Object.is comparison: React uses Object.is() to compare dependencies between renders. This means 0 and -0 are different, but NaN equals NaN (unlike the === operator). Objects and arrays are compared by reference, not by contents.
Performance considerations: Don't overuse useCallback. Only use it when: (1) passing callbacks to optimized child components wrapped in React.memo, (2) the callback is used as a dependency in other hooks like useEffect, or (3) the callback creation is computationally expensive. In most cases, recreating a function is faster than the memoization overhead.
Common misunderstanding: Some developers mistakenly try to pass configuration objects to useCallback thinking it accepts options similar to other APIs. The second parameter is always a dependency array, never a configuration object.
TypeScript protection: If you're using TypeScript with proper React types, the type system will catch this error at compile time: Type 'object' is not assignable to type 'DependencyList | undefined'. This makes the error much easier to catch before runtime.
React 19+ improvements: Future versions of React may introduce useEvent (previously called useEffectEvent) which provides a way to create stable callback references without dependency arrays, solving many common useCallback pain points.
Frequently asked questions
- What does "useCallback was passed a second argument as an object when an array wa" mean?
- The useCallback hook in React requires exactly two arguments: the callback function to memoize, and an array of dependencies that determines when the callback should be recreated. This error appears when you mistakenly pass a plain object {} instead of an array [] as the second parameter. While both arrays and objects are technically "objects" in JavaScript, React specifically requires the dependency list to be an array.
- How do I fix "useCallback was passed a second argument as an object when an array wa"?
- This error occurs when you accidentally pass an object (using curly braces {}) instead of an array (using square brackets []) as the second argument to useCallback. React requires the dependency list to be an array, not a plain object.
- What causes "useCallback was passed a second argument as an object when an array wa"?
- Using curly braces {} instead of square brackets [] for the dependency array Confusion between object literal syntax and array syntax in JavaScript Copy-pasting code that incorrectly formatted the dependencies parameter
- Is the "useCallback was passed a second argument as an object when an array wa" error serious?
- It is a low-severity error — more of a blocker than a risk. The steps above resolve it.
Official resources & further reading
- 📚React Official Documentation
- 📖React Docs: useCallback API Reference(Official Docs)