React: "Invalid Hook Call. Hooks Can Only Be Called Inside the Body of a Function Component"

Three documented causes: calling a hook outside a component function, breaking the Rules of Hooks order, or — the sneaky one — two copies of React in the dependency tree. The first two are code bugs; the third is an npm problem.

What you'll see

Root causes

Hook called outside component render or conditionally

A useState/useEffect in a plain function, a callback, early-returned before the hook, or behind an if. Hooks must run unconditionally, in the same order, during render.

Two React copies (the library-interop classic)

npm ls react shows 2+ versions: a UI library bundling its own React, a hoisting failure, or a monorepo with inconsistent versions. Your component's hook and the renderer's dispatcher come from different Reacts — the call is invalid by identity, not by placement.

Fix it

  1. Check the hook call sites first (cheapest cause)
    # eslint-plugin-react-hooks catches placement/order violations automatically: npx eslint src --ext .js,.jsx
  2. Then check for duplicate React copies
    npm ls react   # any nested second copy = the identity mismatch
  3. Dedupe React
    rm -rf node_modules package-lock.json && npm install   # monorepo: align versions + resolutions/overrides field
  4. Library authors/edge cases: enforce a single instance
    # package.json "resolutions": { "react": "^18.2.0" } (yarn) or "overrides" (npm); or peerDependencies done right in the library

Field note

Minified error #321 IS invalid-hook-call — production builds hide the text, the code identifies it. React's docs list exactly these three causes, in this order of likelihood. The two-React case is the one that 'makes no sense' from a code review: the component is textbook-perfect and the error persists. npm ls react before re-reading your hooks.

Common questions

My hook is at the top of the component. Why the error?

Then it's the React-identity case: check npm ls react for a second copy. The hook IS being called correctly — just against a different React instance than the one rendering it.

Why does reinstalling sometimes fix it?

A clean reinstall re-hoists the tree and can collapse the duplicate React a library dragged in. It's legitimate for this error — but resolutions/overrides in package.json make the fix durable.

Ship it right the first time

Our most-documented failures, packaged as ready-to-ship starter kits: Docker, Kubernetes, and Terraform.

Browse the template store →

One-time. Yours to modify. Instant download from the NinjaOps template store.