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.
Also appears as
- You're importing a component that needs `useState`. This React Hook only works in a Client Component. To fix, mark the file (or its parent) with the `"use client"` directive.
- You're importing a component that needs `useState`. This React hook only works in a client component. To fix, mark the file (or its parent) with the `"use client"` directive.
- You're importing a component that needs useState. It only works in a Client Component but none of its parents are marked with "use client", so they're Server Components by default.
- useState only works in Client Components. Add the "use client" directive at the top of the file to use it. Read more: https://nextjs.org/docs/messages/react-client-hook-in-server-component
- createContext only works in Client Components. Add the "use client" directive at the top of the file to use it. Read more: https://nextjs.org/docs/messages/context-in-server-component
Prompt to fix it
Next.js fails with "You're importing a module that depends on `useState` into a React Server Component module" (older versions say "You're importing a component that needs useState"). Find the Server Component that uses the hook. Move only the interactive part into a separate Client Component file with "use client" as its first line, and keep the page or layout a Server Component that passes serializable props down. For third-party components that use hooks, add a small "use client" wrapper file. Don’t put "use client" on page.tsx or layout.tsx to make the error go away.
Paste into Layerwise or any AI coding tool.
What it means
In the Next.js App Router, every component is a Server Component unless its file starts with 'use client'. Server Components run on the server to produce HTML and never run in the browser, so they can’t hold state, run effects, or handle clicks. Hooks such as useState, useEffect, and useRouter from next/navigation need a Client Component.
'use client' marks a boundary. The file that has it, and everything that file imports, becomes client code. Add it to the smallest component that needs interactivity, such as a button or a form, and keep the page itself a Server Component so its data loading stays on the server.
Putting 'use client' at the top of page.tsx or layout.tsx makes this error go away, but it turns the whole route into client code. Then async components, metadata exports, and secret environment variables stop working there, and you trade this error for new ones.
Common causes
- An AI tool added
useStateoruseEffectto a page or layout file, which is a Server Component by default. - A component file that uses hooks is missing
'use client', or has it below the imports, where Next.js rejects it. - A Server Component imports a library component that uses hooks but doesn’t ship with
'use client'. - A Server Component calls
useRouter,usePathname, oruseSearchParamsfromnext/navigation.
How to fix it
- Open the file named in the error and find the hook it lists.
- Move the interactive part into its own file with
'use client'as the first line, above the imports. - Import that component into the Server Component and pass it data as props. Props must be serializable: strings, numbers, plain objects, and arrays.
- For a third-party component without the directive, create a small file with
'use client'that imports it and exports it again. - In a page, read URL data from the
paramsandsearchParamsprops instead ofusePathnameoruseSearchParams.
Example fix
// app/posts/[id]/like-button.tsx
'use client';
import { useState } from 'react';
export function LikeButton({ initialLikes }: { initialLikes: number }) {
const [likes, setLikes] = useState(initialLikes);
return <button onClick={() => setLikes(likes + 1)}>Like ({likes})</button>;
}
// app/posts/[id]/page.tsx stays a Server Component.
import { LikeButton } from './like-button';
export default async function PostPage({
params
}: {
params: Promise<{ id: string }>;
}) {
const { id } = await params;
const post = await getPost(id);
return <LikeButton initialLikes={post.likes} />;
}Related errors
All errorsReferenceError: window is not defined
Code that only works in a browser ran on the server, where there is no window, document, or localStorage.
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.
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.
Too many re-renders
A component changes its own state while it renders, so React renders it again and again until it stops the loop.
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.