React Server Components vs. Client Components: When to Use Each
The mental model behind the server/client boundary in modern React, with concrete examples of what belongs on each side — and what the next.js app router actually compiles.
- Home-
- Categories-
- React & Next.js-
React Server Components vs. Client Components: When to Use Each
React Server Components vs. Client Components
The one sentence mental model
A Server Component renders where your data lives; a Client Component renders where your user lives. Everything else follows from that sentence.
What Server Components give you
- Direct access to the database and filesystem without an extra API call.
- Zero runtime JavaScript for the parts that only display content.
- Smaller bundles, because libraries used on the server never reach the browser.
What forces a Client Component
- State and effects: `useState`, `useEffect`, event handlers.
- Browser APIs: geometry, media queries, storage.
- Context and interactivity that users feel immediately.
The tricky middle
Props passed from a server component become serialized data, so surprises hide in the boundary.
- Functions and class instances do not survive the boundary.
- Keep client components close to the interaction leaves, and push server components up toward the data roots.
- When a component "is both", split it: a client wrapper with a server body.
How this blog is organised
Pages and post bodies are server-rendered, while the theme toggle and the mobile menu are client islands. That split is why the site stays interactive while shipping a very small amount of JavaScript.
The takeaway
Stop thinking "this component can use hooks, therefore client". Ask where the work should run, then let the framework handle the rest.
Key takeaways
- Ask where the work should run: server components render where the data lives, client components where the user is.
- Keep interactive leaves as client components and push server components up toward the data roots.
- Remember props crossing the boundary become serialized data, so functions and class instances never survive it.
- Split a component that is both into a client wrapper and a server body instead of guessing at the boundary.
- Give display-only sections to the server so you ship zero runtime JavaScript for them.
FAQ
Q: What makes a component a Client Component? A: Not the ability to use hooks, but the work it needs to do. State, effects, event handlers, browser APIs like geometry, media queries and storage, and interactivity users feel immediately are what force a component to be client.
Q: What breaks when I pass props from a Server Component to a Client Component? A: Props crossing that boundary become serialized data, and functions and class instances do not survive it, so surprises hide there. Keep client components near the interaction leaves and push server components up toward the data roots.
2905
you might also like...
The staged path from a slow WordPress site to a fast Next.js one, keeping Persian content, Persian URLs and search traffic intact.
The App Router and React Server Components are not just new APIs; they change where your code runs. Here is how they cut bundle size, simplified data fetching, and made my pages measurably faster.


