How to fix Missing dependency in useEffect: recommended linter config not found in React

ReactBEGINNERMEDIUMUpdated Dec 9, 2025· 99 views

This ESLint warning occurs when the exhaustive-deps rule is not properly configured or when dependencies used inside React hooks are not included in the dependency array, potentially causing stale closures and subtle bugs.

Quick fix

Fixes react-hooks/exhaustive-deps

npm list eslint-plugin-react-hooks
  1. Install eslint-plugin-react-hooks if not already installed
  2. Configure the plugin in your ESLint config file
  3. Add missing dependencies to your dependency arrays
  4. Handle function dependencies with useCallback
react — error
npm list eslint-plugin-react-hooks
Missing dependency in useEffect: recommended linter config not found

What this error means

The "react-hooks/exhaustive-deps" warning appears when ESLint's React Hooks plugin detects that you're using values inside hooks like useEffect, useMemo, or useCallback without including them in the dependency array. This rule is part of eslint-plugin-react-hooks, which is maintained by the React team to enforce the Rules of Hooks. When a value referenced inside these hooks isn't included in the dependency array, React won't re-run the effect or recalculate the value when that dependency changes, leading to stale closures. The component will continue using outdated values from previous renders, causing bugs that are often difficult to debug. The error message specifically about "recommended linter config not found" indicates that your ESLint configuration is either missing the React Hooks plugin entirely, or it's not properly configured to check for exhaustive dependencies in your effects and custom hooks.

Typical symptoms

  • ESLint warning: "React Hook useEffect has a missing dependency"
  • Effects using stale values from props or state
  • Components not updating when expected
  • Inconsistent behavior after state changes
  • No linter warnings despite missing dependencies in hooks
  • Custom hooks not being checked for dependency issues

Common causes

  1. ESLint plugin eslint-plugin-react-hooks is not installed in the project
  2. The exhaustive-deps rule is not enabled in ESLint configuration
  3. Dependencies are omitted from useEffect, useMemo, or useCallback dependency arrays
  4. Variables or functions used in hooks are declared outside without being memoized
  5. Custom hooks are not configured in additionalHooks setting
  6. ESLint configuration uses outdated format or incorrect plugin setup

How to fix "Missing dependency in useEffect: recommended linter config not found"

1Install eslint-plugin-react-hooks if not already installed

First, check if the plugin is installed in your project:

bash
npm list eslint-plugin-react-hooks

If not installed, add it to your project:

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

Or with yarn:

bash
yarn add --dev eslint-plugin-react-hooks
2Configure the plugin in your ESLint config file

For modern ESLint (9.0.0+) using flat config format, edit eslint.config.js:

javascript
import reactHooks from 'eslint-plugin-react-hooks';

export default [
  {
    plugins: {
      'react-hooks': reactHooks
    },
    rules: {
      'react-hooks/rules-of-hooks': 'error',
      'react-hooks/exhaustive-deps': 'warn'
    }
  }
];

For legacy ESLint configuration (.eslintrc.json):

json
{
  "plugins": ["react-hooks"],
  "rules": {
    "react-hooks/rules-of-hooks": "error",
    "react-hooks/exhaustive-deps": "warn"
  }
}

Or in .eslintrc.js:

javascript
module.exports = {
  plugins: ['react-hooks'],
  rules: {
    'react-hooks/rules-of-hooks': 'error',
    'react-hooks/exhaustive-deps': 'warn'
  }
};
3Add missing dependencies to your dependency arrays

Once the rule is configured, ESLint will warn about missing dependencies. Add all referenced values to the dependency array:

Before:

javascript
function MyComponent({ userId }) {
  const [data, setData] = useState(null);

  useEffect(() => {
    fetchUserData(userId).then(setData);
  }, []); // Missing dependency: userId
}

After:

javascript
function MyComponent({ userId }) {
  const [data, setData] = useState(null);

  useEffect(() => {
    fetchUserData(userId).then(setData);
  }, [userId]); // Dependency added
}
4Handle function dependencies with useCallback

If you're passing functions as dependencies, wrap them in useCallback to prevent infinite re-renders:

Before:

javascript
function MyComponent() {
  const handleClick = () => {
    console.log('clicked');
  };

  useEffect(() => {
    handleClick();
  }, [handleClick]); // handleClick recreated every render
}

After:

javascript
import { useCallback } from 'react';

function MyComponent() {
  const handleClick = useCallback(() => {
    console.log('clicked');
  }, []);

  useEffect(() => {
    handleClick();
  }, [handleClick]); // Stable reference
}

Alternatively, move the function inside the effect if it's only used there:

javascript
function MyComponent() {
  useEffect(() => {
    const handleClick = () => {
      console.log('clicked');
    };
    handleClick();
  }, []);
}
5Configure custom hooks validation (optional)

If you have custom hooks that should follow the same dependency rules, configure them using the additionalHooks option:

json
{
  "rules": {
    "react-hooks/exhaustive-deps": [
      "warn",
      {
        "additionalHooks": "(useMyCustomEffect|useMyDataFetcher)"
      }
    ]
  }
}

The value is a regex pattern matching the names of your custom hooks. For ESLint 6.1.1+, you can also use additionalEffectHooks in settings:

json
{
  "settings": {
    "react": {
      "additionalEffectHooks": ["useMyCustomEffect"]
    }
  }
}
6Restart your ESLint server and IDE

After updating your ESLint configuration, restart your development tools:

VS Code:
- Open Command Palette (Cmd/Ctrl + Shift + P)
- Run "ESLint: Restart ESLint Server"
- Or reload the window: "Developer: Reload Window"

WebStorm/IntelliJ:
- File → Invalidate Caches / Restart
- Or simply restart the IDE

Command line:

bash
npx eslint . --ext .js,.jsx,.ts,.tsx

This ensures your editor picks up the new ESLint configuration.

Advanced notes

Understanding Stale Closures

When dependencies are missing, effects capture values from the render when they were created. If those values change in later renders but the effect doesn't re-run, you get a "stale closure" - your effect is still using old values.

When to Disable the Rule

There are legitimate cases to disable the rule using // eslint-disable-next-line react-hooks/exhaustive-deps:

1. Intentionally running only once: When you truly want an effect to run only on mount, despite using external values
2. Using refs: When accessing ref.current values that intentionally don't trigger re-renders
3. Event handlers: When functions are only used for their latest behavior, not their closure

However, these cases are rare. Most of the time, the linter is correct and you should add the dependency.

Memoization Patterns

For objects and arrays, use useMemo to maintain stable references:

javascript
const options = useMemo(() => ({
  method: 'POST',
  headers: { 'Content-Type': 'application/json' }
}), []);

useEffect(() => {
  fetch('/api', options);
}, [options]);

Create React App Note

Projects created with Create React App include this plugin by default with the recommended configuration. If you ejected or are using a custom webpack setup, you'll need to configure it manually.

React 18+ and Concurrent Features

With React 18's concurrent rendering, stale closures can cause even more subtle issues. The exhaustive-deps rule becomes even more critical as effects may be interrupted and restarted, making proper dependency tracking essential for correctness.

Frequently asked questions

What does "react-hooks/exhaustive-deps" mean?
The "react-hooks/exhaustive-deps" warning appears when ESLint's React Hooks plugin detects that you're using values inside hooks like useEffect, useMemo, or useCallback without including them in the dependency array. This rule is part of eslint-plugin-react-hooks, which is maintained by the React team to enforce the Rules of Hooks. When a value referenced inside these hooks isn't included in the dependency array, React won't re-run the effect or recalculate the value when that dependency changes, leading to stale closures.
How do I fix "react-hooks/exhaustive-deps"?
This ESLint warning occurs when the exhaustive-deps rule is not properly configured or when dependencies used inside React hooks are not included in the dependency array, potentially causing stale closures and subtle bugs.
What causes "react-hooks/exhaustive-deps"?
ESLint plugin eslint-plugin-react-hooks is not installed in the project The exhaustive-deps rule is not enabled in ESLint configuration Dependencies are omitted from useEffect, useMemo, or useCallback dependency arrays
Is the "react-hooks/exhaustive-deps" error serious?
It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.

Official resources & further reading