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

ReactBEGINNERMEDIUMUpdated Dec 9, 2025· 97 views

This ESLint error occurs when a React Hook like useContext is called inside a conditional statement, loop, or nested function. React requires all Hooks to be called in the same order on every render to maintain state consistency.

Quick fix

Fixes React Hook "useContext" is called conditionally. React Hooks must be called in the exact same order in every component render.

function MyComponent({ isLoggedIn }) {
  if (isLoggedIn) {
    const user = useContext(UserContext); // ❌ Conditional Hook call
    return <div>Welcome {user.name}</div>;
  }
  return <div>Please log in</div>;
}
  1. Move the Hook call to the top level of your component
  2. Use the Hook value conditionally, not the Hook call itself
  3. For useEffect, put conditions inside the effect callback
  4. Extract conditional logic into separate components
react — error
function MyComponent({ isLoggedIn }) {
if (isLoggedIn) {
const user = useContext(UserContext); // ❌ Conditional Hook call
return <div>Welcome {user.name}</div>;
}
return <div>Please log in</div>;
}
React Hook "useContext" 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 rule "rules-of-hooks" when it detects a Hook being called conditionally. React Hooks rely on a consistent call order to associate each Hook with its internal state. When you call a Hook inside an if statement, loop, or nested function, that Hook might be skipped on some renders, breaking React's ability to track which state belongs to which Hook call. React maintains an internal linked list of Hooks for each component. Every time your component renders, React expects the same Hooks to be called in the same order. If a Hook is sometimes present and sometimes absent (due to conditional execution), the positions in this list shift, causing React to lose track of the state and potentially leading to bugs that are extremely difficult to debug. This rule applies to all Hooks: useState, useEffect, useContext, useReducer, useCallback, useMemo, useRef, and any custom Hooks you create. The ESLint plugin enforces this rule at build time to prevent these runtime errors.

Typical symptoms

  • ESLint warning: "React Hook is called conditionally" in your IDE or terminal
  • Build fails with eslint-plugin-react-hooks errors
  • Component state becomes inconsistent or mixed up between renders
  • Unexpected "Rendered more hooks than during the previous render" errors at runtime
  • Hook values don't update as expected or reference wrong state

Common causes

  1. Calling a Hook inside an if, else, or switch statement
  2. Calling a Hook inside a loop (for, while, forEach, map)
  3. Calling a Hook inside a nested function or callback that might not execute
  4. Calling a Hook after an early return statement
  5. Conditionally calling a Hook based on props or state values

How to fix "React Hook "useContext" 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

Ensure all Hooks are called at the very beginning of your function component, before any conditional logic or early returns.

Before (incorrect):

javascript
function MyComponent({ isLoggedIn }) {
  if (isLoggedIn) {
    const user = useContext(UserContext); // ❌ Conditional Hook call
    return <div>Welcome {user.name}</div>;
  }
  return <div>Please log in</div>;
}

After (correct):

javascript
function MyComponent({ isLoggedIn }) {
  const user = useContext(UserContext); // ✅ Always called

  if (isLoggedIn) {
    return <div>Welcome {user.name}</div>;
  }
  return <div>Please log in</div>;
}
2Use the Hook value conditionally, not the Hook call itself

Call the Hook unconditionally, then use conditional logic with the value it returns.

Before (incorrect):

javascript
function UserProfile({ showTheme }) {
  if (showTheme) {
    const theme = useContext(ThemeContext); // ❌ Conditional Hook call
    return <div className={theme}>Profile</div>;
  }
  return <div>Profile</div>;
}

After (correct):

javascript
function UserProfile({ showTheme }) {
  const theme = useContext(ThemeContext); // ✅ Always called

  return <div className={showTheme ? theme : ''}>Profile</div>;
}
3For useEffect, put conditions inside the effect callback

Don't conditionally call useEffect. Instead, call it unconditionally and handle conditions inside the effect function.

Before (incorrect):

javascript
function DataFetcher({ shouldFetch }) {
  if (shouldFetch) {
    useEffect(() => {  // ❌ Conditional Hook call
      fetchData();
    }, []);
  }
}

After (correct):

javascript
function DataFetcher({ shouldFetch }) {
  useEffect(() => {  // ✅ Always called
    if (shouldFetch) {
      fetchData();
    }
  }, [shouldFetch]);
}
4Extract conditional logic into separate components

If you need truly different Hook behavior based on conditions, split your component into smaller components where each always calls the same Hooks.

Before (incorrect):

javascript
function Dashboard({ userType }) {
  if (userType === 'admin') {
    const adminData = useContext(AdminContext); // ❌ Conditional Hook call
    return <AdminDashboard data={adminData} />;
  }
  return <UserDashboard />;
}

After (correct):

javascript
function AdminDashboardWrapper() {
  const adminData = useContext(AdminContext); // ✅ Always called in this component
  return <AdminDashboard data={adminData} />;
}

function Dashboard({ userType }) {
  if (userType === 'admin') {
    return <AdminDashboardWrapper />;
  }
  return <UserDashboard />;
}
5Verify ESLint configuration includes react-hooks plugin

Ensure your ESLint configuration has the react-hooks plugin enabled to catch these errors during development.

Add to your .eslintrc.js or eslintrc.json:

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

If using Create React App, this is included by default. For other setups, install the plugin:

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

Advanced notes

Why React enforces Hook order:

React doesn't use names or identifiers to track Hooks. Instead, it relies entirely on call order. Each Hook call gets the next slot in an internal array. This design allows Hooks to work without requiring you to manually specify unique keys, but it also means the order must never change between renders.

Custom Hooks follow the same rules:

Custom Hooks are just functions that call built-in Hooks, so they must also be called unconditionally:

javascript
// ❌ Wrong
if (condition) {
  useCustomHook();
}

// ✅ Correct
useCustomHook(); // Then handle condition inside the custom Hook

Early returns are safe after all Hooks:

You can return early from a component as long as all Hooks have already been called:

javascript
function Component({ user }) {
  const theme = useContext(ThemeContext); // ✅ Called first
  const [count, setCount] = useState(0);  // ✅ Called second

  if (!user) {
    return null; // ✅ Safe - all Hooks already called
  }

  return <div className={theme}>{count}</div>;
}

Performance considerations:

Calling Hooks unconditionally doesn't hurt performance. Hooks are extremely lightweight, and calling them without using their values is negligible. React's reconciliation optimizations handle this efficiently.

TypeScript and type narrowing:

When you move a Hook call outside a conditional, you might need to handle null/undefined cases in your types:

typescript
function Component({ enabled }: { enabled: boolean }) {
  const value = useContext(MyContext); // Always called, might be null

  if (enabled && value) {
    // TypeScript knows value is non-null here
    return <div>{value.data}</div>;
  }
  return null;
}

Frequently asked questions

What does "React Hook "useContext" is called conditionally. React Hooks must be c" mean?
This error is triggered by the eslint-plugin-react-hooks rule "rules-of-hooks" when it detects a Hook being called conditionally. React Hooks rely on a consistent call order to associate each Hook with its internal state. When you call a Hook inside an if statement, loop, or nested function, that Hook might be skipped on some renders, breaking React's ability to track which state belongs to which Hook call.
How do I fix "React Hook "useContext" is called conditionally. React Hooks must be c"?
This ESLint error occurs when a React Hook like useContext is called inside a conditional statement, loop, or nested function. React requires all Hooks to be called in the same order on every render to maintain state consistency.
What causes "React Hook "useContext" is called conditionally. React Hooks must be c"?
Calling a Hook inside an if, else, or switch statement Calling a Hook inside a loop (for, while, forEach, map) Calling a Hook inside a nested function or callback that might not execute
Is the "React Hook "useContext" is called conditionally. React Hooks must be c" error serious?
It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.

Official resources & further reading