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.

Browser console
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://react.dev/link/invalid-hook-call for tips about how to debug and fix this problem.

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 useEffect callback, or a .then() callback instead of at the top of the component.
  • A component library or linked local package installs its own copy of react next to the app’s.
  • A shared package in a monorepo lists react under dependencies instead of peerDependencies, 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

  1. Run npm ls react react-dom in the app folder. Every entry should show the same version, with repeats marked deduped.
  2. If a package brings its own React, list react and react-dom in its peerDependencies, or pin one version with overrides in the app’s package.json, then reinstall.
  3. For linked or monorepo packages in a Vite app, add resolve: { dedupe: ['react', 'react-dom'] } to vite.config.ts.
  4. 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.
  5. Turn on the react-hooks ESLint 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>;
}
All errors
Rendered more hooks than during the previous render.

Rendered 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 module that depends on `useState` into a React Server Component module. This API is only available in Client Components. To fix, mark the file (or its parent) with the `"use client"` directive. Learn more: https://nextjs.org/docs/app/api-reference/directives/use-client

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.

TypeError: Cannot read properties of undefined (reading 'map')

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 because the server rendered HTML didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used: - A server/client branch `if (typeof window !== 'undefined')`. - Variable input such as `Date.now()` or `Math.random()` which changes each time it's called. - Date formatting in a user's locale which doesn't match the server. - External changing data without sending a snapshot of it along with the HTML. - Invalid HTML tag nesting. It can also happen if the client has a browser extension installed which messes with the HTML before React loaded. https://react.dev/link/hydration-mismatch

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.