How to fix useCallback was passed a second argument as an object when an array was expected in React

ReactBEGINNERLOWUpdated Dec 8, 2025· 121 views

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
  1. Locate the problematic useCallback call
  2. Replace curly braces with square brackets
  3. List dependencies correctly in the array
  4. Handle object dependencies properly
react — error
// 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
useCallback 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

  1. Using curly braces {} instead of square brackets [] for the dependency array
  2. Confusion between object literal syntax and array syntax in JavaScript
  3. Copy-pasting code that incorrectly formatted the dependencies parameter
  4. Mistakenly trying to pass a configuration object as the second parameter
  5. Auto-complete or IDE suggestion inserting wrong syntax
  6. Mixing up useCallback syntax with other hooks that accept object parameters
  7. Refactoring code and accidentally changing brackets to braces
  8. 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"

1Locate the problematic useCallback call

Find the useCallback hook that's causing the error. Look for code that passes curly braces as the second argument:

javascript
// 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

The error message in your console will typically point to the specific file and line number where this occurs.

2Replace curly braces with square brackets

Change the second argument from object notation {} to array notation []:

javascript
// CORRECT - using array syntax
const memoizedCallback = useCallback(() => {
  doSomething(value);
}, [value]); // ✅ Array with dependency

// CORRECT - empty dependency array
const memoizedCallback = useCallback(() => {
  doSomething();
}, []); // ✅ Empty array

This is the core fix - ensuring the second parameter is an array, not an object.

3List dependencies correctly in the array

Include all values from component scope that the callback uses:

javascript
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.

4Handle object dependencies properly

If you need to depend on object values, extract specific properties or use useMemo:

javascript
// 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 reference

Passing entire objects as dependencies can cause unnecessary re-renders because objects are compared by reference, not by value.

5Verify the fix with ESLint

Install and configure the React Hooks ESLint plugin to catch dependency issues automatically:

bash
npm install eslint-plugin-react-hooks --save-dev

Add to your ESLint configuration:

json
{
  "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.

6Test callback memoization behavior

Verify that your callback is now memoizing correctly:

javascript
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