JS Guide
HomeQuestionsTopicsCompaniesResources
BookmarksSearch

Built for developers preparing for JavaScript, React & TypeScript interviews.

ResourcesQuestionsSupport
HomeQuestionsSearchProgress
HomeTopicsnextjsServer & Client Components
PrevNext
nextjs
intermediate
10 min read

Server & Client Components

client-components
composition
nextjs
react
server-components
ssr
use-client

In the App Router, all components are Server Components by default — they render on the server with zero client JavaScript, can directly access backend resources, and pass serializable props to Client Components marked with 'use client' that handle interactivity (state, effects, event handlers).

Key Points

1Server Components (Default)

Render on server only, zero client JS, can be async with direct DB/API access. Cannot use hooks, event handlers, or browser APIs.

2Client Components ('use client')

Pre-rendered via SSR then hydrated on client. Support hooks, events, browser APIs. Ship JavaScript to the browser.

3Boundary Placement

Push 'use client' as far down the tree as possible — the directive makes everything below it in the import tree client-side.

4Serialization Rule

Props from Server to Client Components must be serializable — no functions, classes, or Dates. Use children prop to compose Server Components inside Client Components.

What You'll Learn

  • Explain the difference between Server Components and Client Components
  • Know which features are available in each component type (hooks, async, backend access)
  • Apply the composition pattern to minimize the client boundary
  • Understand the serialization constraint on Server-to-Client props

Deep Dive

The Server Component / Client Component model is the most significant architectural change in Next.js. Understanding the boundary between them is essential for building efficient applications.

Server Components (Default)

Every component in the App Router is a Server Component unless you add 'use client'. Server Components:

  • Render entirely on the server — their JavaScript never reaches the browser
  • Can directly access databases, file systems, and environment variables
  • Can be async — await data fetches, database queries, or API calls directly in the component
  • Reduce client-side bundle size — large dependencies used only in Server Components don't ship to the browser
  • Cannot use React hooks (useState, useEffect, useRef) or browser APIs
  • Cannot attach event handlers (onClick, onChange)
TypeScript
// This is a Server Component (default)
async function UserProfile({ userId }: { userId: string }) {
  const user = await db.users.findById(userId); // Direct DB access
  return <div>{user.name}</div>;
}

Client Components

Client Components are marked with 'use client' at the top of the file. They:

  • Are pre-rendered on the server (SSR) for initial HTML, then hydrate on the client
  • Can use hooks (useState, useEffect, useRef, useContext)
  • Can attach event handlers and use browser APIs
  • Ship their JavaScript to the browser
  • Cannot be async or directly access backend resources
JavaScript
'use client';
import { useState } from 'react';
 
function Counter() {
  const [count, setCount] = useState(0);
  return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
}

The Boundary Rule

When a file has 'use client', every component imported into that file becomes a Client Component — the directive creates a boundary. Everything below the boundary in the import tree is client-side.

This means: push 'use client' as far down the component tree as possible. Only the interactive parts need to be Client Components — keep data fetching, layout, and static content as Server Components.

Composition Pattern

Server Components can pass Client Components as children or props:

TSX
// ServerLayout.tsx (Server Component)
import { InteractiveWidget } from './InteractiveWidget';
 
async function ServerLayout() {
  const data = await fetchData();
  return (
    <div>
      <h1>{data.title}</h1>
      <InteractiveWidget>{/* Server Component children */}</InteractiveWidget>
    </div>
  );
}

Client Components can render Server Components passed via children — but Client Components cannot import and render Server Components directly.

Serialization Boundary

Props passed from Server Components to Client Components must be serializable — no functions, classes, or Date objects. Serializable types: strings, numbers, booleans, arrays, plain objects, null, undefined, Map, Set, and typed arrays.

When to Use Each

  • Server Component: Data fetching, accessing backend resources, heavy dependencies (markdown parsing, syntax highlighting), static UI, SEO content
  • Client Component: User interactions (clicks, forms, modals), state management, browser APIs (localStorage, geolocation), real-time updates, animations

Common Mistakes

  • Putting 'use client' on layout or page components — this makes everything below them client-side, losing Server Component benefits
  • Trying to use hooks in Server Components — no useState, useEffect, or context in server code
  • Importing server-only code (database clients, secrets) in Client Components — this would expose secrets

Key Interview Distinction

Server Components render on the server with zero client JS — they can be async and access backend resources directly. Client Components ('use client') handle interactivity and ship JS to the browser. Push the 'use client' boundary as low as possible. Props across the boundary must be serializable. Server Components can pass Client Components as children, but Client Components cannot import Server Components directly.

Fun Fact

React Server Components were developed over 3+ years before shipping. The React team published an RFC in December 2020 and demonstrated them in a talk that broke the internet — the idea of components that never ship JavaScript to the client was radical. Next.js 13 (October 2022) was the first production framework to ship Server Components, making them mainstream.

Learn These First

Next.js Fundamentals

beginner

Continue Learning

Rendering Strategies

advanced

Data Fetching

intermediate

Practice What You Learned

What's the difference between Server Components and Client Components in Next.js?
mid
components
Server Components render on the server with no JavaScript sent to the client, ideal for data fetching and static content. Client Components (marked with 'use client') render on both server and client, enabling interactivity like state and event handlers.
Previous
Caching & Revalidation
Next
Data Fetching
PrevNext