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()orconst 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+Ron Windows/Linux,Cmd+Shift+Ron 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-hookscatches all three causes at lint time. Set it up once and stop debugging this error forever.

