React Hook useEffect Has a Missing Dependency – ESLint Warning Explained | FreeLearning365.com

React Hook useEffect Has a Missing Dependency – ESLint Warning Explained | FreeLearning365.com
🔥 ESLint Rules Guide

React Hook useEffect Has a
Missing Dependency — ESLint Warning Explained

⚡ React Hook useEffect has a missing dependency: '...'. Either include it or remove the dependency array.

React 19 • Next.js 15 • TypeScript • Vite • React Router • Redux Toolkit

📘 FreeLearning365.com 🕒 Updated July 20, 2026 13 min read

📝 What Does “React Hook useEffect Has a Missing Dependency” Mean?

The “React Hook useEffect has a missing dependency” warning is one of the most common ESLint warnings you'll encounter in React development. It appears when the useEffect hook uses a variable or function that isn't listed in its dependency array.

The full warning message reads:

                    React Hook useEffect has a missing dependency: 'someVariable'.
                    Either include it or remove the dependency array.
                

Why does this warning exist? The exhaustive-deps ESLint rule ensures that your useEffect hooks include all values they depend on. This prevents:

  • Stale closures — Using outdated values from previous renders.
  • Missing re-runs — Not updating when dependencies change.
  • Hard-to-debug bugs — Silent failures that only appear in specific scenarios.
  • Infinite loops — When state updates rely on stale values.
✅ Good news: This warning is your friend! It helps you catch bugs early and write more predictable React code.
🚨 Important: Ignoring this warning without understanding why it appears can lead to subtle bugs in production. Always fix the root cause.

⚡ Quick Reference — Common Solutions at a Glance

✅ Add the missing dependency
Include the variable in the dependency array: [variable].
🟠 Use useCallback for functions
Memoize functions with useCallback to stabilize references.
🟣 Use useMemo for values
Memoize computed values with useMemo.
🔴 Use functional updates
For state updates, use setState(prev => ...).
🔵 Use useReducer for complex state
Reducer actions are stable and reduce dependency issues.

📋 Golden Rules for useEffect Dependencies

  • 📋 Include all values used in the effect — State, props, context, and any derived values.
  • 🔄 Use useCallback for functions — Functions passed as dependencies should be memoized.
  • 📦 Use useMemo for derived values — Computed values used in the effect.
  • Use functional updates for statesetState(prev => ...) to avoid dependency on state.
  • 🔧 Don't ignore the warning — Understand why it appears and fix it properly.
  • 📝 Use eslint-disable-next-line sparingly — Only when the warning is truly a false positive.

🧩 Detailed Breakdown — Every Scenario Solved

Each card below dives deep into one specific scenario involving missing dependencies, with root causes, code examples, and step-by-step fixes.

🛡️ Prevention — Avoid Missing Dependency Warnings

🔹 1. Use the ESLint exhaustive-deps Rule
Install eslint-plugin-react-hooks and enable the rule in your ESLint config.
🔹 2. Think About Side Effects
Ask yourself: "What values does this effect depend on?" List all of them.
🔹 3. Use useCallback for Functions
Any function used in useEffect should be memoized with useCallback.
🔹 4. Use useMemo for Computed Values
Derived values used in effects should be memoized to prevent unnecessary re-renders.
🔹 5. Use useReducer for Complex State
Reducer actions are stable and can reduce dependency issues in effects.
💡 Pro Tip: In React 19, the new use hook for promises handles data fetching differently and may not trigger the same dependency warnings as useEffect.

❓ Frequently Asked Questions

What happens if I ignore the missing dependency warning?

Ignoring the warning can lead to stale closures — your effect will use outdated values from the first render, even if the values have changed.

For example, if your effect depends on userId but you don't include it in the dependency array, the effect will always use the initial userId, even after it changes.

🚨 Warning: This is a common source of bugs in React apps. Always fix the warning by adding the missing dependency or using the appropriate pattern.
Should I always add all dependencies to the array?

Yes, in most cases. The exhaustive-deps rule is designed to help you catch bugs. Adding all dependencies is the safest approach.

However, there are exceptions:

  • Functions from useCallback — If the function is memoized, it's stable.
  • Dispatch from useReducer — The dispatch function is stable.
  • Refsref.current changes don't trigger re-renders.

In these cases, you can safely ignore the warning or use eslint-disable-next-line with a comment explaining why.

Does React 19 change the dependency rules?

No. React 19 maintains the same dependency rules as React 18. The exhaustive-deps ESLint rule still applies to useEffect and useLayoutEffect.

React 19's new use hook for promises works differently — it doesn't have the same dependency requirements, which can be a nice alternative for data fetching.

✅ React 19 compatibility: All fixes in this guide work perfectly with React 19 and Next.js 15.
How do I fix the warning when the dependency is a function?

When a function is used in useEffect, you have two options:

  1. Wrap it in useCallback — This stabilizes the function reference.
  2. Move it inside the effect — If the function is only used in that effect.
// ✅ Option 1: useCallback
                        const fetchData = useCallback(() => {
                          // ... function logic
                        }, [deps]);

                        useEffect(() => {
                          fetchData();
                        }, [fetchData]); // ✅ Stable dependency

                        // ✅ Option 2: Move inside effect
                        useEffect(() => {
                          const fetchData = () => {
                            // ... function logic
                          };
                          fetchData();
                        }, [deps]);
💡 Pro Tip: Moving the function inside the effect is the simplest fix and often the cleanest approach.
What about missing dependencies in useCallback and useMemo?

The same rule applies! useCallback and useMemo also require exhaustive dependencies. If you use a variable inside them and don't list it, ESLint will warn you.

// ❌ Wrong — missing dependency in useCallback
                        const handleClick = useCallback(() => {
                          console.log(count); // Uses count
                        }, []); // 👈 Missing count!

                        // ✅ Correct — include count
                        const handleClick = useCallback(() => {
                          console.log(count);
                        }, [count]); // ✅ count in deps

Always include all values used inside useCallback and useMemo to avoid stale closures.

When is it okay to use eslint-disable-next-line?

Only in specific cases where the warning is a false positive.

Acceptable cases:

  • useReducer dispatch function (stable).
  • useRef object (stable, changes don't trigger re-renders).
  • setState function from useState (stable).
  • When you intentionally want the effect to run only once.

Always add a comment explaining why:

// ✅ Acceptable — dispatch is stable
                        useEffect(() => {
                          dispatch({ type: 'LOAD_DATA' });
                        }, [dispatch]); // ✅ dispatch is stable

                        // ✅ Acceptable — intentional once-only effect
                        useEffect(() => {
                          // One-time initialization
                        }, []); // eslint-disable-line react-hooks/exhaustive-deps
⚠️ Warning: Don't use eslint-disable as a lazy fix. Always understand why the warning appears before disabling it.

📘 FreeLearning365.com  —  Master React, Next.js, TypeScript & the modern web stack.

Built with ❤️ for developers everywhere.

Post a Comment

0 Comments