Free tutorials & notes in Hindi & English · Clean code examples 🧰 Free PDF & Image Tools →
🟣 Data, Server & APIs  ·  Lesson 18

Server vs Client Components

Everything is a Server Component by default

In the App Router, every component is a Server Component unless you say otherwise. It runs on the server, can read files and databases directly, and sends only HTML to the browser — zero JavaScript for that component.

JSX – Server Component
// app/courses/page.jsx — Server Component (no directive needed)
import { courses } from '@/lib/courses'
import fs from 'node:fs'                 // ✅ Node APIs allowed on the server

export default async function Courses() {
  const note = fs.readFileSync('notice.txt', 'utf8')   // runs on server only
  return (
    <main>
      <p>{note}</p>
      {courses.map((c) => <h2 key={c.slug}>{c.title}</h2>)}
    </main>
  )
}

Client Components: 'use client'

When you need interactivity — clicks, typing, state, browser APIs — put 'use client' at the top of the file.

JSX – components/LikeButton.jsx
// components/LikeButton.jsx — Client Component
'use client'                              // must be the very first line
import { useState } from 'react'

export default function LikeButton() {
  const [likes, setLikes] = useState(0)
  return <button onClick={() => setLikes(likes + 1)}>👍 {likes}</button>
}

When to use which

You need…ServerClient
Fetch data / query database✅⚠️ via API
Keep API keys secret✅❌
onClick, onChange, forms with live validation❌✅
useState, useEffect, useContext❌✅
window, localStorage, geolocation❌✅
Small JavaScript bundle✅adds JS

What runs where

BrowserNext.js serverDatabaseGET /coursesServer Component: SELECT coursesrowsHTML + small JS for client partshydrate CourseSearch (client)
Server Components never ship their code; client parts hydrate
Serverpage.jsx, CourseCard, data fetching — HTML onlyClientCourseSearch, Header menu, LikeButton — HTML + JS
Two kinds of components in one page

The client boundary

'use client' marks a boundary. That file and everything it imports become client code. So put the directive as low in the tree as possible.

layout.jsxserverpage.jsxserverCourseSearch.jsx 'use client'boundaryInput.jsx (imported)client automatically
Everything below the boundary is client code

Pattern: server page + small client island

JSX – app/courses/page.jsx (EduSite)
// app/courses/page.jsx (Server Component)
import { searchCourses } from '@/lib/courses'
import CourseCard from '@/components/CourseCard'   // server
import CourseSearch from './CourseSearch'          // client island

export default async function CoursesPage({ searchParams }) {
  const { q = '' } = await searchParams
  const list = searchCourses(q)                     // data on server
  return (
    <div className="container">
      <h1>All Courses</h1>
      <CourseSearch initial={q} />                  {/* only this ships JS */}
      <div className="grid">
        {list.map((c) => <CourseCard key={c.slug} course={c} />)}
      </div>
    </div>
  )
}
Courses page: server rendered cards with a client search box
Cards are Server Components; only the search box is a Client Component

Passing Server Components as children

A Client Component cannot import a Server Component, but it can receive one as a prop or children.

JSX – composition
// components/Tabs.jsx  (client)
'use client'
import { useState } from 'react'
export default function Tabs({ first, second }) {
  const [tab, setTab] = useState(0)
  return (
    <div>
      <button onClick={() => setTab(0)}>Syllabus</button>
      <button onClick={() => setTab(1)}>Reviews</button>
      {tab === 0 ? first : second}
    </div>
  )
}

// app/courses/[slug]/page.jsx  (server)
<Tabs
  first={<Syllabus slug={slug} />}   // Server Components passed as props
  second={<Reviews slug={slug} />}   // they still render on the server
/>

Keeping secrets on the server

JS – lib/db.js
// lib/db.js
import 'server-only'          // npm i server-only → build error if imported in client code
import mysql from 'mysql2/promise'
export const db = mysql.createPool({ password: process.env.DB_PASSWORD /* … */ })

Environment variables without the NEXT_PUBLIC_ prefix are never sent to the browser.

Common mistakes

  • Adding 'use client' to page.jsx just for one button → the whole page ships JS. Extract the button.
  • Passing functions as props from Server to Client (onSave={save}) → not serializable; use a Server Action instead.
  • Using window in a Server Component → "window is not defined".
  • 'use client' after imports → it must be the first line.

Summary

  • Server Components (default): data, secrets, zero JS.
  • Client Components ('use client'): state, events, browser APIs.
  • Keep client islands small and pass server content as children.
✅ Practice

Make a server-rendered course page and add a client LikeButton and a client Tabs component that receives two server-rendered sections as props.

Frequently Asked Questions

Are Client Components rendered only in the browser?
No. Client Components are also pre-rendered to HTML on the server for the first load, then hydrated in the browser so they become interactive.
Can a Server Component use useState?
No. Hooks like useState, useEffect and event handlers like onClick need the browser, so those components must be Client Components.
Do I need 'use client' in every interactive file?
Only at the entry point of the client part. Files imported by a 'use client' file are already client code.
Why are Server Components better for performance?
Their JavaScript is never sent to the browser. Only the resulting HTML is sent, so the bundle stays small and pages load faster.
← Next.js Tutorial
🔗

Share this topic with a friend

यह topic किसी दोस्त को भेजें

Found it useful? Send it to a classmate learning the same thing.

अच्छा लगा? जो दोस्त यही सीख रहा है, उसे भेज दीजिए।

Next topicData Fetching & Caching Your progress: 18 / 37 (49%) · Lesson 19 / 37 Continue →

How was this lesson?

Your feedback helps us make the content better.

Write a review or suggestion (optional)

After approval, your name and city may appear publicly with your review. Please do not write your email or phone number.

▶ CodingEasily on YouTube

Learn with video lessons in easy Hindi

Featured video: RDBMS Part 3 – Class XI Commerce IT

▶ Subscribe – it’s free