Invalid hook call
A hook such as useState ran somewhere React can’t track it, or the app loaded two copies of React that don’t know about each other.
Also appears as
- TypeError: Cannot read properties of null (reading 'useState')
- Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: 1. You might have mismatching versions of React and the renderer (such as React DOM) 2. You might be breaking the Rules of Hooks 3. You might have more than one copy of React in the same app See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
- Minified React error #321; visit https://react.dev/errors/321 for the full message or use the non-minified dev environment for full errors and additional helpful warnings.
Prompt to fix it
My React app shows "Invalid hook call. Hooks can only be called inside of the body of a function component." First run npm ls react react-dom and tell me whether there is more than one copy. If there is, fix the dependencies so the app uses a single React: peerDependencies for shared packages, overrides in package.json, or resolve.dedupe in Vite. Then look for hooks called inside event handlers, effects, callbacks, class components, or outside components, and move them to the top level of a component or custom hook. Don’t downgrade React to make the error go away.
Paste into Layerwise or any AI coding tool.
What it means
Hooks are the React functions whose names start with use, such as useState and useEffect. React tracks them per component while it renders, so it only accepts calls made directly in a function component or in a custom hook. A call from an event handler, an effect callback, a class component, or plain code outside any component happens when React isn’t listening.
The other common cause has nothing to do with where you call the hook: two copies of React in one app. A component library or a linked local package brings its own react, and its hooks talk to a copy that isn’t rendering the page. When that happens, you usually also see Cannot read properties of null (reading 'useState').
So run npm ls react before you change any component. If it lists more than one version, or a copy that isn’t marked deduped, fix the install first.
Common causes
- A hook is called inside an event handler, a
useEffectcallback, or a.then()callback instead of at the top of the component. - A component library or linked local package installs its own copy of
reactnext to the app’s. - A shared package in a monorepo lists
reactunderdependenciesinstead ofpeerDependencies, so it gets a separate copy. - A hook is called from a class component or from code at the top level of a module.
How to fix it
- Run
npm ls react react-domin the app folder. Every entry should show the same version, with repeats markeddeduped. - If a package brings its own React, list
reactandreact-domin itspeerDependencies, or pin one version withoverridesin the app’spackage.json, then reinstall. - For linked or monorepo packages in a Vite app, add
resolve: { dedupe: ['react', 'react-dom'] }tovite.config.ts. - Move each hook call to the top level of a function component or a custom hook, and use the value it returns inside handlers and effects.
- Turn on the
react-hooksESLint rules so the editor flags misplaced hooks as you type.
Example fix
import { useNavigate } from 'react-router';
export function SaveButton() {
// Call the hook while rendering, then use its result in the handler.
// onClick={() => useNavigate()('/done')} would call it outside render.
const navigate = useNavigate();
return <button onClick={() => navigate('/done')}>Save</button>;
}Related errors
All errorsRendered more hooks than during the previous render
A component called a different number of hooks than on its last render, usually because a hook sits after an early return or inside an if.
You’re importing a component that needs useState
A Next.js Server Component used a browser-side React feature like useState, which only works in files marked as Client Components.
Cannot read properties of undefined
The code asked for a property of a value that doesn’t exist yet, usually data that hasn’t loaded or a field the API didn’t return.
Hydration failed
The HTML the server sent didn’t match what React rendered first in the browser, so React threw that part away and rebuilt it on the client.
Build with an agent that checks its work
The Layerwise agent clicks through the live preview and reads the console, so it catches errors before you do.