How to fix React Hook "useState" is called conditionally in React

ReactBEGINNERHIGHUpdated Dec 10, 2025· 83 views

React Hook 'useState' is called conditionally, which violates the Rules of Hooks. Hooks must always be called at the top level of your component, before any early returns or conditional statements.

Quick fix

Fixes INVALID_HOOK_CALL

// ❌ WRONG - useState inside condition
function MyComponent({ isUser }) {
  if (isUser) {
    const [name, setName] = useState('');
  }
  return <div></div>;
}

// ✅ CORRECT - useState at top level
function MyComponent({ isUser }) {
  const [name, setName] = useState('');

  if (isUser) {
    return <div>{name}</div>;
  }
  return <div>Not logged in</div>;
}
  1. Move the state declaration to the top level
  2. Move conditions inside hooks instead
  3. Use separate components for different logic branches
  4. Verify with ESLint plugin
react — error
// ❌ WRONG - useState inside condition
function MyComponent({ isUser }) {
if (isUser) {
const [name, setName] = useState('');
}
return <div></div>;
}
// ✅ CORRECT - useState at top level
function MyComponent({ isUser }) {
const [name, setName] = useState('');
if (isUser) {
return <div>{name}</div>;
}
return <div>Not logged in</div>;
}
React Hook "useState" is called conditionally

What this error means

In React, hooks like useState follow a specific rule: they must be called in the same order every time a component renders. React internally tracks hooks using an array, and when you call a hook conditionally (inside an if statement, loop, or after an early return), the order of hooks can change between renders. When the order changes, React cannot correctly match each hook call to its stored state, causing incorrect behavior or crashes. This is why React enforces the "Rules of Hooks" - to ensure hooks are always called in a consistent, predictable order.

Typical symptoms

  • Error message: "React Hook \"useState\" is called conditionally"
  • Components behave erratically after conditionally calling hooks
  • State values become out of sync with their intended purpose
  • Different number of hooks called on different renders
  • ESLint warning from eslint-plugin-react-hooks plugin

Common causes

  1. Calling useState inside an if/else statement
  2. Calling useState inside a loop (for, while, etc.)
  3. Calling useState after an early return statement
  4. Calling useState inside nested functions or callbacks
  5. Toggling hook calls between renders based on conditions

How to fix "React Hook "useState" is called conditionally"

1Move the state declaration to the top level

Call useState at the very top of your component function, before any conditional logic. This ensures the hook is always called in the same order.

jsx
// ❌ WRONG - useState inside condition
function MyComponent({ isUser }) {
  if (isUser) {
    const [name, setName] = useState('');
  }
  return <div></div>;
}

// ✅ CORRECT - useState at top level
function MyComponent({ isUser }) {
  const [name, setName] = useState('');

  if (isUser) {
    return <div>{name}</div>;
  }
  return <div>Not logged in</div>;
}
2Move conditions inside hooks instead

If you need conditional logic, move the condition inside the hook (useEffect, useMemo, etc.) rather than wrapping the hook itself.

jsx
// ❌ WRONG - conditional hook
function MyComponent({ shouldFetch }) {
  if (shouldFetch) {
    const [data, setData] = useState(null);
  }
}

// ✅ CORRECT - condition inside hook
function MyComponent({ shouldFetch }) {
  const [data, setData] = useState(null);

  useEffect(() => {
    if (shouldFetch) {
      // Fetch logic here
    }
  }, [shouldFetch]);
}
3Use separate components for different logic branches

If you have completely different rendering logic, consider extracting each branch into its own component. Each component can have its own hooks.

jsx
// Component with hooks for authenticated users
function UserProfile() {
  const [profile, setProfile] = useState(null);
  // ... user-specific hooks
  return <div>{profile.name}</div>;
}

// Component with hooks for guests
function GuestView() {
  const [guestData, setGuestData] = useState(null);
  // ... guest-specific hooks
  return <div>Welcome, guest!</div>;
}

// Main component - conditional rendering of components, not hooks
function MyComponent({ isUser }) {
  return isUser ? <UserProfile /> : <GuestView />;
}
4Verify with ESLint plugin

Make sure you have eslint-plugin-react-hooks installed and configured. This will catch violations automatically.

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

Add to your .eslintrc.json:

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

Advanced notes

The Rules of Hooks exist because of how React implements hooks internally. React maintains a "fiber" (component instance) with a linked list of hooks. Each hook occupies a fixed position in this list. When you call hooks conditionally, React cannot guarantee that the same hook will be at the same position on every render, causing state and effects to be associated with the wrong hooks.

This is why the order of hooks must be deterministic and unconditional. The only way to conditionally run a hook's effect is to move the condition inside the hook itself, typically using useEffect with a dependency array.

Remember: Hooks can only be called at the top level or inside custom hooks (which themselves must follow the same rules). They cannot be called in classes, regular functions, or nested functions outside of hooks.

Frequently asked questions

What does "INVALID_HOOK_CALL" mean?
In React, hooks like useState follow a specific rule: they must be called in the same order every time a component renders. React internally tracks hooks using an array, and when you call a hook conditionally (inside an if statement, loop, or after an early return), the order of hooks can change between renders. When the order changes, React cannot correctly match each hook call to its stored state, causing incorrect behavior or crashes.
How do I fix "INVALID_HOOK_CALL"?
React Hook 'useState' is called conditionally, which violates the Rules of Hooks. Hooks must always be called at the top level of your component, before any early returns or conditional statements.
What causes "INVALID_HOOK_CALL"?
Calling useState inside an if/else statement Calling useState inside a loop (for, while, etc.) Calling useState after an early return statement
Is the "INVALID_HOOK_CALL" 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