How to fix React Hook useCallback has a missing dependency. Either include it or remove the dependency array in React

ReactINTERMEDIATEMEDIUMUpdated Dec 8, 2025ยท 148 views

This ESLint warning occurs when a variable or function used inside useCallback is not listed in its dependency array. The react-hooks/exhaustive-deps rule enforces complete dependency tracking to prevent stale closures and ensure callbacks update when their dependencies change.

Quick fix

Fixes React Hook useCallback has a missing dependency. Either include it or remove the dependency array

// Before: Missing dependency warning
const handleClick = useCallback(() => {
  console.log(userId); // userId not in dependencies
}, []);

// After: Include the missing dependency
const handleClick = useCallback(() => {
  console.log(userId);
}, [userId]); // Now callback updates when userId changes
  1. Add the missing dependency to the array
  2. Move the function inside the callback if it's only used there
  3. Use functional updates for state setters
  4. Wrap object or array dependencies in useMemo
react โ€” error
// Before: Missing dependency warning
const handleClick = useCallback(() => {
console.log(userId); // userId not in dependencies
}, []);
// After: Include the missing dependency
const handleClick = useCallback(() => {
console.log(userId);
}, [userId]); // Now callback updates when userId changes
React Hook useCallback has a missing dependency. Either include it or remove the dependency array

What this error means

This warning is triggered by the ESLint plugin react-hooks/exhaustive-deps rule when it detects that a callback function passed to useCallback references variables, props, or state that are not included in the dependency array. The rule exists to prevent common bugs where callbacks capture stale values from previous renders. When you use useCallback, React memoizes the callback function and only recreates it when one of the dependencies in the array changes. If you reference a variable inside the callback but don't include it in the dependency array, the callback will continue using the old value from when it was first created, even if that value has changed in subsequent renders. This creates a "stale closure" problem that can lead to incorrect behavior. The exhaustive-deps rule analyzes your callback body and compares all referenced values against your dependency array. It warns you about any missing dependencies so you can decide whether to add them, restructure your code, or (rarely) explicitly acknowledge that you want the stale behavior.

Typical symptoms

  • Yellow ESLint warning appears in your IDE or terminal: "React Hook useCallback has a missing dependency"
  • The warning specifies which dependency is missing and suggests including it or removing the dependency array
  • Callback function behaves incorrectly, using outdated values from previous renders
  • Event handlers or memoized callbacks don't reflect latest prop or state changes
  • Build process shows warnings when running npm run build or yarn build
  • Component behavior differs between development and production builds
  • Functions passed to child components don't update when expected

Common causes

  1. Referencing props inside useCallback without including them in the dependency array
  2. Using state variables inside the callback that aren't listed as dependencies
  3. Calling other functions inside useCallback that reference props or state
  4. Accessing object properties or array elements that change between renders
  5. Using variables from component scope that depend on props or state
  6. Intentionally omitting dependencies to prevent callback recreation, causing stale closures
  7. Copying code from useEffect examples without adapting the dependency array
  8. Misunderstanding how closure scope works in React hooks

How to fix "React Hook useCallback has a missing dependency. Either include it or remove the dependency array"

1Add the missing dependency to the array

The most straightforward solution is to include all referenced variables in the dependency array. Review the ESLint warning to identify which dependency is missing, then add it:

tsx
// Before: Missing dependency warning
const handleClick = useCallback(() => {
  console.log(userId); // userId not in dependencies
}, []);

// After: Include the missing dependency
const handleClick = useCallback(() => {
  console.log(userId);
}, [userId]); // Now callback updates when userId changes

This ensures the callback is recreated whenever the dependency changes, preventing stale closures.

2Move the function inside the callback if it's only used there

If you're calling another function inside useCallback, and that function references props or state, consider moving it inside the callback or wrapping it in its own useCallback:

tsx
// Before: Helper function causes dependency issues
function processData(value: string) {
  return value + userId; // References userId from component scope
}

const handleSubmit = useCallback(() => {
  const result = processData(input);
  // ...
}, [input]); // Missing userId dependency

// After: Move function inside callback
const handleSubmit = useCallback(() => {
  function processData(value: string) {
    return value + userId; // Now clearly requires userId
  }
  const result = processData(input);
  // ...
}, [input, userId]); // All dependencies explicit
3Use functional updates for state setters

If your callback updates state based on the current state value, use the functional update form instead of referencing state directly. This eliminates the need to include state in dependencies:

tsx
// Before: State in dependencies
const increment = useCallback(() => {
  setCount(count + 1); // References current count
}, [count]); // Callback recreated every time count changes

// After: Functional update removes dependency
const increment = useCallback(() => {
  setCount(prev => prev + 1); // No reference to count
}, []); // Stable callback, never recreated

This pattern is especially useful for event handlers that should remain stable across renders.

4Wrap object or array dependencies in useMemo

Objects and arrays created inline get new references every render, causing useCallback to recreate the function even if the content hasn't changed. Memoize them first:

tsx
// Before: Object recreated every render
const config = { apiKey, timeout: 5000 };
const fetchData = useCallback(() => {
  api.fetch(config); // config is a new object every time
}, [config]); // Callback recreates on every render

// After: Memoize the object
const config = useMemo(() => ({
  apiKey,
  timeout: 5000
}), [apiKey]);

const fetchData = useCallback(() => {
  api.fetch(config);
}, [config]); // Now only recreates when apiKey changes
5Extract static values outside the component

If a value never changes, move it outside the component so it doesn't need to be a dependency:

tsx
// Before: Constant in component scope
function MyComponent() {
  const API_ENDPOINT = 'https://api.example.com';

  const fetchData = useCallback(() => {
    fetch(API_ENDPOINT); // ESLint wants this as dependency
  }, []); // Warning about missing API_ENDPOINT
}

// After: Move constant outside
const API_ENDPOINT = 'https://api.example.com';

function MyComponent() {
  const fetchData = useCallback(() => {
    fetch(API_ENDPOINT); // No longer a dependency
  }, []); // No warning
}
6Use useRef for values that shouldn't trigger updates

If you need to reference a value inside the callback but don't want changes to that value to recreate the callback, store it in a ref:

tsx
// Before: Callback recreates on every analytics change
const handleClick = useCallback(() => {
  analytics.track('click', { userId });
}, [userId, analytics]); // Analytics object changes frequently

// After: Store analytics in ref
const analyticsRef = useRef(analytics);
analyticsRef.current = analytics; // Keep ref updated

const handleClick = useCallback(() => {
  analyticsRef.current.track('click', { userId });
}, [userId]); // Callback only recreates when userId changes

Use this pattern sparingly and only when you're certain the callback doesn't need to update when the ref'd value changes.

7Disable the warning only as a last resort

If you've carefully considered your use case and determined the dependency should intentionally be omitted (rare), you can disable the warning with a comment:

tsx
const handleMount = useCallback(() => {
  // This should only run once on mount, not when userId changes
  initializeComponent(userId);
  // eslint-disable-next-line react-hooks/exhaustive-deps
}, []); // Intentionally empty despite using userId

Warning: Only use this if you fully understand the implications. Missing dependencies usually indicate real bugs. Document why the dependency is intentionally omitted and consider if useEffect might be more appropriate.

Advanced notes

Understanding the exhaustive-deps rule: The react-hooks/exhaustive-deps ESLint rule is part of the eslint-plugin-react-hooks package. It analyzes your hook code statically and warns about any values used inside hooks that aren't in the dependency array. This rule works with useCallback, useMemo, useEffect, and custom hooks that follow the dependencies pattern.

When callbacks recreate too often: If adding all dependencies causes your callback to recreate on every render, it defeats the purpose of memoization. This usually indicates a code structure issue. Consider: (1) whether you actually need useCallback at all - it's only beneficial when passing callbacks to memoized child components or using them in other hook dependencies, (2) whether upstream values should be memoized first with useMemo, or (3) whether your component is doing too much and should be split.

Custom hooks and dependencies: If you're writing custom hooks that accept dependency arrays, you can configure the exhaustive-deps rule to validate them using the additionalHooks option in your ESLint config. This ensures your custom hooks receive the same lint protection as built-in hooks.

React Compiler future: The experimental React Compiler (formerly React Forget) aims to automatically memoize components and hooks without requiring manual useCallback, useMemo, or dependency arrays. When it's stable, many of these warnings may become obsolete. Until then, follow the exhaustive-deps rule.

Performance considerations: Don't use useCallback prematurely for performance. Wrapping every function in useCallback actually adds overhead unless those functions are passed to optimized components wrapped in React.memo or used as dependencies in other hooks. Profile first, optimize second.

Debugging stale closures: If you suspect a stale closure bug, add a console.log inside your callback to see which values it's capturing. Compare those values to what you expect. If they're outdated, you're missing a dependency. The React DevTools Profiler can also help identify components rendering unnecessarily due to changing callbacks.

Frequently asked questions

What does "React Hook useCallback has a missing dependency. Either include it or" mean?
This warning is triggered by the ESLint plugin react-hooks/exhaustive-deps rule when it detects that a callback function passed to useCallback references variables, props, or state that are not included in the dependency array. The rule exists to prevent common bugs where callbacks capture stale values from previous renders. When you use useCallback, React memoizes the callback function and only recreates it when one of the dependencies in the array changes.
How do I fix "React Hook useCallback has a missing dependency. Either include it or"?
This ESLint warning occurs when a variable or function used inside useCallback is not listed in its dependency array. The react-hooks/exhaustive-deps rule enforces complete dependency tracking to prevent stale closures and ensure callbacks update when their dependencies change.
What causes "React Hook useCallback has a missing dependency. Either include it or"?
Referencing props inside useCallback without including them in the dependency array Using state variables inside the callback that aren't listed as dependencies Calling other functions inside useCallback that reference props or state
Is the "React Hook useCallback has a missing dependency. Either include it or" error serious?
It is a medium-severity error โ€” more of a blocker than a risk. The steps above resolve it.

Official resources & further reading