dev3 ·
I am moving a project to the Next.js 15 App Router. Every file seems to be a server component by default, but when I add useState I get an error. When should I use "use client" and what actually changes?
0
DEV3 Developer Forum
Every post is reviewed first. Usually reviewed within 24 hours.
I am moving a project to the Next.js 15 App Router. Every file seems to be a server component by default, but when I add useState I get an error. When should I use "use client" and what actually changes?
Short version: in the App Router every component is a React Server Component (RSC) unless the file (or a file that imports it) starts with "use client".
async, read databases, files and secrets directly.useState, useEffect, event handlers or browser APIs."use client" at the top of the file.window, and most interactive libraries.// app/products/page.tsx (server)
import { db } from "@/lib/db";
import AddToCart from "./add-to-cart";
export default async function Page() {
const products = await db.product.findMany();
return products.map((p) => (
<div key={p.id}>
{p.name} <AddToCart id={p.id} />
</div>
));
}
// app/products/add-to-cart.tsx
"use client";
import { useState } from "react";
export default function AddToCart({ id }: { id: string }) {
const [n, setN] = useState(0);
return <button onClick={() => setN(n + 1)}>Add ({n})</button>;
}
"use client" as low in the tree as possible (a small button, not the whole page).children or props, not imported inside it.Date, Map/Set and Promises are fine; class instances and functions are not, except Server Actions).server-only.Pitfall: putting "use client" in a layout makes everything it imports client code, which hurts bundle size.