nextjs-client-components-vs-server-components-explained-simply
And then the confusion starts:
- When should I use Client Components?
- When should I use Server Components?
- What actually runs on the browser vs the server?
- Will I break SEO or performance if I choose wrong?
Let’s clear this up in simple language, with a mental model you can reuse in any project.
1. First idea: Think in terms of
“Where does this code run?”
- Server Component → runs on the server.
- Client Component → runs in the browser.
That’s the core idea.
In Next.js App Router:
- By default, every component is a Server Component.
- If you add "use client" at the top of a file, that file becomes a Client Component.
2. What is a Server Component (in human terms)?
A Server Component is a React component that:
- Runs only on the server
- Can safely access:
- Database
- Backend APIs
- Secrets (keys, tokens)
- Does not ship its JS logic to the browser
- Can render HTML and send it to the client
You can think of it as:
“React component that behaves like a smart template on the server.”
Key properties of Server Components
- ✅ Great for SEO (HTML is rendered on the server)
- ✅ Great for performance (less JavaScript sent to client)
- ✅ Can do data fetching directly (no need for useEffect or fetch in the client)
- ❌ Cannot use browser-only APIs (window, document, localStorage, etc.)
- ❌ Cannot use React hooks that depend on the browser (useState, useEffect, useRef for DOM stuff)
3. What is a Client Component (in human terms)?
A Client Component is a React component that:
- Runs in the user’s browser
- Supports all the typical React stuff:
- useState, useEffect, useRef
- Event handlers like onClick, onChange, etc.
- Browser APIs like window, document, localStorage
- Needs "use client" at the top of the file
You can think of it as:
“Interactive widgets that live in the browser — buttons, forms, dropdowns, modals, etc.”
Key properties of Client Components
- ✅ Needed for buttons, dropdowns, forms, modals, animations
- ✅ Needed for browser APIs (local storage, cookies on client, scroll events)
- ❌ More JavaScript is shipped to the browser
- ❌ Harder to keep ultra-fast if everything is client-side
4. The golden rule:
“Most of your tree should be Server Components.
Only make interactive parts Client Components.”
In Next.js App Router, best practice is:
Use Server Components by default.
Drop into Client Components only when you need interactivity.
So your page usually looks like:
- Layout → Server
- Page → Server
- Big sections → Server
- Small UI widgets inside → Client
Example mental model:
In this example:
- The overall page is rendered on the server for performance and SEO.
- Only the ContactForm (which needs form state, validation, maybe live feedback) is a Client Component.
5. How do you make a Client Component?
Simple: add "use client" at the top of the file.
This file is compiled for the browser and gets hydrated on the client.
6. Data fetching: where should it happen?
With Server Components
You can fetch data directly at the top level of your component:
This code:
- Runs on the server
- Can talk directly to your database or internal APIs
- Sends fully rendered HTML to the browser
No useEffect, no loading spinners unless you want them.
With Client Components
If you fetch inside a Client Component, it behaves like classic React:
- You use useEffect, fetch, axios, etc.
- Data is fetched from the browser
- You might get loading states and spinners
Best practice: fetch data in Server Components, then pass it down to Client Components as props.
Example:
7. What can’t you do in a Server Component?
Things that require the browser:
- useState, useEffect, useLayoutEffect
- Event handlers like onClick, onChange, etc.
- (you CAN write them in JSX, but they won’t work unless the component is client-side)
- Accessing:
- window
- document
- localStorage
- DOM APIs
- Using client-side libraries like:
- Chart libraries designed for the browser
- framer-motion
- react-hook-form (usually)
- Most UI libraries that expect a browser environment
If you need any of these → move that component to Client with "use client".
8. Can a Client Component import a Server Component?
No.
- A Server Component can import a Client Component.
- But a Client Component cannot import a Server Component.
Why?
Because Server Components may contain server-only code (DB calls, secrets). That can’t be bundled into browser JS.
So the direction is always:
Server → Client (allowed)
Client → Server (not allowed)
If you accidentally try to import a Server Component into a Client Component, Next.js will complain.
9. Common patterns (with examples)
Pattern 1: Server page, client widget
Pattern 2: Client layout section only
Sometimes you want sticky nav with scroll effects or theme toggles.
10. Performance: why Server Components are a big deal
Next.js pushes you towards Server Components because they solve a big problem:
too much JavaScript in the browser.
Benefits of Server Components:
- No component logic shipped to client
- Can stream HTML to the browser
- Easier to keep bundle size small
- Can do heavy work on the server (queries, data merging, auth, etc.)
Compare:
- Classic SPA → large JS bundle, more hydration work
- RSC + Next.js → only interactive parts hydrate on client
So a good rule:
If your component doesn’t need interactivity, keep it as a Server Component.
11. Cheat sheet: When to pick what?
Use a Server Component when:
- You are rendering static or data-driven UI
- You need to query a database, CMS, or external API
- You care about SEO
- You don’t need useState / useEffect
- The component is mostly just layout / content
Examples:
- Blog pages
- Product details
- Dashboard shell
- Static marketing sections
- Navigation that doesn’t need scroll/hover JS tricks
Use a Client Component when:
- You need state (useState)
- You need side effects (useEffect)
- You are handling events (onClick, onChange, etc.)
- You use browser APIs (window, document, localStorage)
- You use interactive libraries (charts, modals, sliders, forms)
Examples:
- Forms with validation and live feedback
- Theme toggle (dark/light)
- Menus, dropdowns, accordions
- Drag-and-drop interfaces
- Complex chart components
- Chat input box
12. Migrating your thinking (if you’re coming from CRA / older Next.js)
If you’re used to “everything is a client component”, this will feel weird at first.
Old mindset:
Fetch in useEffect → set state → render.
New mindset (Next.js App Router):
Fetch on the server → pass data into components → add client islands only where absolutely needed.
So instead of:
You now do:
This small shift gives you huge performance wins.
13. Final mental model (keep this in your head)
When you’re confused, ask these questions:
- Does this component need interactivity or browser APIs?
- Yes → Client Component
- No → Server Component
- Can I fetch data on the server instead of the client?
- Yes → Do it in a Server Component
- Can I keep most of the page server-side and only make small pieces client-side?
- Yes → That’s usually the best option.
14. Short recap
- Next.js App Router uses Server Components by default.
- Add "use client" at the top to make a Client Component.
- Server Components:
- Run only on server
- Great for data fetching & SEO
- No interactivity directly
- Client Components:
- Run in browser
- Needed for state, effects, events & browser APIs
- Best practice:
“Keep most of your UI as Server Components.
Use Client Components only for interactive islands.”
Once this clicks, Next.js suddenly feels much simpler — and your app becomes faster almost for free.

