Fix "Invalid hook call. Hooks can only be called inside of the body of a function component." in React

beginner⚛️ React2026-03-21| React 16.8+, any OS, any bundler (Vite, Webpack, CRA, Next.js)

Error Message

Invalid hook call. Hooks can only be called inside of the body of a function component.
#react#hooks#rules-of-hooks#function-component

What just happened

Your React app was working fine — then suddenly a blank screen. Open the console and you see:

Error: Invalid hook call. Hooks can only be called inside of the body of a function component.

This is a hard crash, not a warning. React refuses to render anything until you fix it.

Three things cause this error. Work through them in order — the first one trips up most developers.

Cause 1: Two copies of React in your project

More common than you'd think, especially after installing a UI library like Material UI, Ant Design, or a local package you're building yourself.

How to check

Run this in your project root:

npm ls react

Or with pnpm/yarn:

pnpm why react
yarn why react

See React listed at two different paths? That's your problem. Your app runs one copy. The library runs another. When the library calls a hook, React can't find the shared state context — crash.

Fix

If the duplicate comes from a local package you're developing (symlinked via npm link or a monorepo workspace), point the library at your app's React. In the library's webpack config:

// webpack.config.js (in your library)
const path = require('path');

module.exports = {
  // ...
  resolve: {
    alias: {
      react: path.resolve('./node_modules/react'),
    },
  },
};

For Vite:

// vite.config.js (in your library)
import { defineConfig } from 'vite';
import path from 'path';

export default defineConfig({
  resolve: {
    alias: {
      react: path.resolve('./node_modules/react'),
    },
  },
});

If the duplicate comes from a third-party package, mismatched peer dependencies are usually the culprit. Update React and do a clean reinstall:

npm install react@latest react-dom@latest
rm -rf node_modules package-lock.json
npm install

Cause 2: Calling a hook outside a function component

useState, useEffect, useRef — any function prefixed with use — must be called directly inside a function component or a custom hook. That's it. Anywhere else and React throws this error.

Common mistakes

Hook inside a regular function:

// WRONG — regular function, not a component
function fetchUserData(userId) {
  const [data, setData] = useState(null); // Error!
  // ...
}

// CORRECT — move the hook into the component
function UserProfile({ userId }) {
  const [data, setData] = useState(null);

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

  return {data?.name};
}

Hook inside an event handler:

// WRONG
function LoginButton() {
  function handleClick() {
    const [token, setToken] = useState(''); // Error!
  }

  return Login;
}

// CORRECT — state lives at the component level
function LoginButton() {
  const [token, setToken] = useState('');

  function handleClick() {
    setToken('abc123');
  }

  return Login;
}

Hook inside a conditional:

// WRONG — hooks can't live inside if/else
function Dashboard({ isLoggedIn }) {
  if (isLoggedIn) {
    const [profile, setProfile] = useState(null); // Error!
  }
}

// CORRECT — always call the hook; conditionally act on the value
function Dashboard({ isLoggedIn }) {
  const [profile, setProfile] = useState(null);

  useEffect(() => {
    if (isLoggedIn) {
      fetchProfile().then(setProfile);
    }
  }, [isLoggedIn]);
}

Cause 3: Hooks inside a class component

Hooks don't work in class components — period. This bites people mid-migration: they start adding useState without converting the class first.

// WRONG — class component + hooks = error
class UserCard extends React.Component {
  render() {
    const [count, setCount] = useState(0); // Error!
    return {count};
  }
}

// CORRECT — convert to a function component
function UserCard() {
  const [count, setCount] = useState(0);
  return {count};
}

Can't convert the whole class right now? Extract the hook logic into a small child function component and render it inside the class. Not pretty, but it unblocks you.

Quick diagnostic checklist

  • Run npm ls react — more than one version listed?
  • Is the hook at the top level of a function component — not inside if, for, or a nested function?
  • Is the component a function (function Foo() or const Foo = () =>), not a class?
  • Does the component name start with a capital letter? React uses this to tell components apart from regular functions.
  • Are you calling a custom hook that internally calls another hook from the wrong context?

Verify the fix

Once you've made the change:

  • Clear your browser console.
  • Hard-refresh (Ctrl+Shift+R on Windows/Linux, Cmd+Shift+R on Mac).
  • The Invalid hook call error should be gone.
  • Your component renders without crashing.

Want to catch this before it ever reaches the browser? Install the ESLint plugin:

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

Add it to your ESLint config:

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

The plugin flags bad hook calls as you type — no need to run the app to find out.

Key takeaways

  • Got the error right after installing a library? Check for duplicate React copies first. It's the sneakiest cause and the most common.
  • Hooks belong at the top level of a function component or custom hook — no conditions, no loops, no nested functions.
  • eslint-plugin-react-hooks catches all three causes at lint time. Set it up once and stop debugging this error forever.

Related Error Notes