How to fix React Hook "useEffect" is called conditionally. React Hooks must be called in the exact same order in every component render. in React

ReactBEGINNERHIGHUpdated Dec 22, 2025· 98 views

This ESLint error occurs when useEffect or other React Hooks are called conditionally, inside loops, or after early returns. React requires all Hooks to be called in the same order on every render to maintain internal state consistency.

Quick fix

Fixes react-hooks/rules-of-hooks

function MyComponent({ isEnabled }) {
  if (!isEnabled) {
    return <div>Disabled</div>;
  }

  // ❌ Error: Hook called after early return
  useEffect(() => {
    console.log('Component mounted');
  }, []);

  return <div>Enabled</div>;
}
  1. Move the Hook call to the top level of your component
  2. Move conditional logic inside the Hook
  3. Extract Hooks to a separate child component
  4. Use dependency arrays for conditional execution
react — error
function MyComponent({ isEnabled }) {
if (!isEnabled) {
return <div>Disabled</div>;
}
// ❌ Error: Hook called after early return
useEffect(() => {
console.log('Component mounted');
}, []);
return <div>Enabled</div>;
}
React Hook "useEffect" is called conditionally. React Hooks must be called in the exact same order in every component render.

What this error means

This error is triggered by the eslint-plugin-react-hooks linting rule that enforces React's fundamental Rules of Hooks. The error appears when you place a Hook call (like useEffect, useState, useCallback, etc.) inside a conditional statement, loop, or nested function, or after an early return statement. React Hooks rely on call order to maintain their internal state between renders. Each Hook call is tracked by React using a numeric index based on the order in which Hooks are called. If the order changes between renders—such as when a Hook is conditionally called—React loses track of which state belongs to which Hook, causing bugs and unexpected behavior. The eslint-plugin-react-hooks package, developed by the React team, automatically detects these violations during development to prevent runtime bugs that would be difficult to debug.

Typical symptoms

  • ESLint error in your IDE or terminal: "React Hook is called conditionally"
  • Build or lint process fails with react-hooks/rules-of-hooks violation
  • Component behavior becomes unpredictable when conditions change between renders
  • State values get mixed up between different Hook calls
  • React DevTools shows incorrect Hook values or state

Common causes

  1. Placing useEffect or other Hooks inside if/else statements or ternary operators
  2. Calling Hooks after an early return statement in a component
  3. Using Hooks inside loops (for, while, forEach, map)
  4. Placing Hooks inside nested functions or callbacks
  5. Conditionally rendering logic that includes Hook calls without moving Hooks to a child component
  6. Using Hooks inside try/catch blocks or switch statements

How to fix "React Hook "useEffect" is called conditionally. React Hooks must be called in the exact same order in every component render."

1Move the Hook call to the top level of your component

The simplest fix is to ensure all Hooks are called at the top of your component function, before any conditional logic or early returns.

Before (incorrect):

tsx
function MyComponent({ isEnabled }) {
  if (!isEnabled) {
    return <div>Disabled</div>;
  }

  // ❌ Error: Hook called after early return
  useEffect(() => {
    console.log('Component mounted');
  }, []);

  return <div>Enabled</div>;
}

After (correct):

tsx
function MyComponent({ isEnabled }) {
  // ✅ Hook called at top level
  useEffect(() => {
    console.log('Component mounted');
  }, []);

  if (!isEnabled) {
    return <div>Disabled</div>;
  }

  return <div>Enabled</div>;
}
2Move conditional logic inside the Hook

Instead of conditionally calling the Hook, call it unconditionally but add your condition inside the Hook's callback. This ensures the Hook runs on every render while the logic executes conditionally.

Before (incorrect):

tsx
function MyComponent({ shouldFetch, userId }) {
  // ❌ Error: Hook called conditionally
  if (shouldFetch) {
    useEffect(() => {
      fetchUserData(userId);
    }, [userId]);
  }

  return <div>Content</div>;
}

After (correct):

tsx
function MyComponent({ shouldFetch, userId }) {
  // ✅ Hook always called, condition inside
  useEffect(() => {
    if (!shouldFetch) {
      return; // Early return inside the effect
    }

    fetchUserData(userId);
  }, [shouldFetch, userId]);

  return <div>Content</div>;
}
3Extract Hooks to a separate child component

When you need to conditionally use Hooks based on props or state, create a child component that contains the Hook calls, then conditionally render that component.

Before (incorrect):

tsx
function Dashboard({ user }) {
  if (user.isAdmin) {
    // ❌ Error: Hook called conditionally
    useEffect(() => {
      loadAdminData();
    }, []);
  }

  return <div>Dashboard</div>;
}

After (correct):

tsx
function AdminEffects() {
  // ✅ Hook always called in this component
  useEffect(() => {
    loadAdminData();
  }, []);

  return null; // This component only runs effects
}

function Dashboard({ user }) {
  return (
    <div>
      {user.isAdmin && <AdminEffects />}
      Dashboard
    </div>
  );
}
4Use dependency arrays for conditional execution

For effects that should only run when certain values change, rely on the dependency array instead of conditional Hook calls.

Before (incorrect):

tsx
function SearchResults({ query }) {
  // ❌ Error: Hook called conditionally
  if (query.length > 0) {
    useEffect(() => {
      searchAPI(query);
    }, [query]);
  }

  return <div>Results</div>;
}

After (correct):

tsx
function SearchResults({ query }) {
  // ✅ Hook always called, dependencies control execution
  useEffect(() => {
    if (query.length === 0) {
      return;
    }

    searchAPI(query);
  }, [query]); // Effect re-runs when query changes

  return <div>Results</div>;
}

Advanced notes

Why Hook Order Matters:
React doesn't use names or IDs to track Hooks—it uses the order in which they're called. React maintains an internal array of Hook state, and each call to a Hook like useState or useEffect corresponds to an index in that array. When Hook calls are conditional, the indices shift between renders, causing React to return the wrong state values.

ESLint Configuration:
The react-hooks/rules-of-hooks rule is part of eslint-plugin-react-hooks. Ensure your ESLint config includes:

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

Custom Hooks Follow the Same Rules:
Custom Hooks (functions starting with "use") must also follow these rules. Any Hook calls inside your custom Hooks must be unconditional:

tsx
// ❌ Incorrect
function useCustomHook(shouldRun) {
  if (shouldRun) {
    useEffect(() => { /* ... */ }, []);
  }
}

// ✅ Correct
function useCustomHook(shouldRun) {
  useEffect(() => {
    if (!shouldRun) return;
    // ... effect logic
  }, [shouldRun]);
}

False Positives:
Occasionally, ESLint may flag code that appears conditional but actually isn't (e.g., after complex control flow). In rare cases where you're certain the code is correct, you can disable the rule for that line:

tsx
// eslint-disable-next-line react-hooks/rules-of-hooks
useEffect(() => { /* ... */ }, []);

However, this should be a last resort—most of the time, the linter is correctly identifying a real issue.

Frequently asked questions

What does "react-hooks/rules-of-hooks" mean?
This error is triggered by the eslint-plugin-react-hooks linting rule that enforces React's fundamental Rules of Hooks. ) inside a conditional statement, loop, or nested function, or after an early return statement. React Hooks rely on call order to maintain their internal state between renders.
How do I fix "react-hooks/rules-of-hooks"?
This ESLint error occurs when useEffect or other React Hooks are called conditionally, inside loops, or after early returns. React requires all Hooks to be called in the same order on every render to maintain internal state consistency.
What causes "react-hooks/rules-of-hooks"?
Placing useEffect or other Hooks inside if/else statements or ternary operators Calling Hooks after an early return statement in a component Using Hooks inside loops (for, while, forEach, map)
Is the "react-hooks/rules-of-hooks" error serious?
Yes. This is a high-severity error that usually blocks work until it is fixed, but the steps above resolve it.

Official resources & further reading