Invalid hook call (React Hooks rules / duplicate React)
React refused a Hook call because the call site broke the Rules of Hooks, or because more than one copy of React is loaded so Hook state is not shared with the component that rendered.
How it shows up
Error: 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
at resolveDispatcher
at useState …
Dev builds often print the three-reason checklist. Production may only show the short Invalid hook call line.
What React expects
- Hooks run only while React is rendering a function component (or a custom Hook that was itself called from one).
- Same order every render — no hooks inside loops, conditions, or after early
return. - One React module instance shared by your app and
react-dom/ React Native.
vs hydration failed
| Error | Means |
|---|---|
| Invalid hook call | Hook API used outside a valid render, or duplicate/mismatched React so there is no dispatcher |
| Hydration failed / Text content does not match | Server HTML and client first render disagree — still a valid component tree |
| Rendered more hooks than during the previous render | Hook count changed between renders (conditional hooks) — cousin of Rules-of-Hooks breaks |
Cause 1 — Rules of Hooks broken
// Bad: hook in a plain function
function loadUser() {
const [user, setUser] = useState(null); // Invalid hook call
…
}
// Bad: conditional hook
function Profile({ id }) {
if (!id) return null;
const [user, setUser] = useState(null); // order/presence changes
…
}
// Good: hooks at top level of a function component
function Profile({ id }) {
const [user, setUser] = useState(null);
if (!id) return null;
…
}
// Good: custom hook named use…
function useUser(id) {
const [user, setUser] = useState(null);
useEffect(() => { … }, [id]);
return user;
}
Cause 2 — duplicate React
npm/yarn/pnpm can nest a second react under a library. Then your component uses React A’s dispatcher while the library’s hooks talk to React B — Invalid hook call.
# See how many physical copies you have
npm ls react
pnpm why react
yarn why react
# Often in a linked local package / monorepo:
# peerDependencies on react + bundler alias / dedupe
Fixes that usually work: declare react / react-dom as peerDependencies in libraries; hoist/dedupe so only one version resolves; in Webpack/Vite alias both react and react-dom to the app’s node_modules/react. Compare two lockfile trees in the text diff tool if needed.
Cause 3 — mismatched renderer
- React 18 app with an old
react-dom(or the reverse). - Importing
react-dom/clientAPIs while another bundle still ships an ancient React. - Using hooks from
reactinside a non-React runtime (plain Node script, wrong test renderer).
npm ls react react-dom
# Align versions deliberately, e.g. both 18.3.x or both 19.x
Fix checklist
- Move every
use*call to the top level of a function component or custom Hook. - Run
npm ls react— if you see more than one version/path, dedupe or alias. - Match
reactandreact-dom(and React Native) major/minor as your stack documents. - In monorepos, ensure the package under test resolves React from the workspace root.
- If the stack trace points at a third-party UI kit, upgrade it or force resolutions until
npm ls reactis flat. - Hydration warnings without Invalid hook call → use the hydration failed guide instead.
Related
React hydration failed · Module not found: Can't resolve · Cannot find module (Node) · npm ERESOLVE · npm ERR! code ELIFECYCLE · TypeError: Failed to fetch · Cannot GET / (Express)
Questions
What does Invalid hook call mean?
React rejected a Hook because it was not called during a function component render, or because multiple React copies mean there is no shared Hooks dispatcher.
Can I call hooks in ordinary functions?
No. Call them only from React function components or from custom Hooks (functions named use… that are themselves only called from components/Hooks).
Why do duplicate React copies break hooks?
Each React copy has its own Hook state. Your component may render with one copy while a library’s useState runs against another — Invalid hook call.
How do I check for duplicate React?
Run npm ls react (or pnpm why / yarn why). More than one physical path usually means you need peerDependencies, hoisting, or a bundler alias.
How is this different from hydration failed?
Hydration failed means server HTML and the client’s first render disagree. Invalid hook call is about Hook call sites or multiple Reacts, not HTML mismatch.
Do conditional hooks cause this?
Often they cause “Rendered more hooks than during the previous render”. Calling hooks only after an early return can also surface as Invalid hook call depending on the path.
Can the wrong react-dom version cause it?
Yes. Mismatched react and react-dom (or an old renderer) is reason (1) in React’s own error text.
Published .