Next.js Tutorial
- Next.js Introduction
- Next.js Installation
- Project Structure
- Pages & Routing
- Dynamic Routing
- Linking & Navigating
- Data Fetching (SSR)
- Data Fetching (SSG)
- Client-Side Rendering
- API Routes
- Layouts & Components
- Styling
- Image Optimization
- Font Optimization
- Script Optimization
- Middleware
- Environment Variables
- Error Handling
- Authentication
- React Server Components
- Server Actions
- Suspense & Streaming
- Caching & Revalidation
- TypeScript Integration
- Deployment
Client-Side Rendering (CSR)
While Next.js excels at Server-Side Rendering (SSR) and Static Site Generation (SSG), there are still many scenarios where traditional Client-Side Rendering (CSR) is entirely appropriate or necessary.
When should you use CSR?
- Highly Interactive UI: Applications that require constant, complex state updates and user interactions (like a spreadsheet or a web-based game).
- User-specific data after login: If a dashboard is locked behind an authentication wall and does not need SEO, fetching the heavy data on the client saves server resources.
- Accessing Browser APIs: If your component relies on
window,document, orlocalStorage, it MUST be rendered on the client because those APIs do not exist on a Node server.
CSR in the App Router
By default, all components in the App router (app/) are Server Components. To write a client-side rendered component, you MUST declare it at the top of the file using the 'use client' directive.
'use client'; // This directive opts into CSR!
import { useState, useEffect } from 'react';
export default function Dashboard() {
const [data, setData] = useState(null);
useEffect(() => {
fetch('/api/user/data')
.then(res => res.json())
.then(json => setData(json));
}, []);
if (!data) return <p>Loading your dashboard...</p>;
return <div>Welcome back, {data.username}!</div>;
}Using SWR or React Query
The Next.js team recommends against using raw `useEffect` for data fetching due to caching and deduplication issues. Instead, they created a powerful data fetching library called SWR (Stale-While-Revalidate).
import useSWR from 'swr';
const fetcher = (...args) => fetch(...args).then(res => res.json());
export default function Profile() {
// SWR automatically handles caching, revalidation, focus tracking, and more!
const { data, error, isLoading } = useSWR('/api/user', fetcher);
if (error) return <div>Failed to load user data</div>;
if (isLoading) return <div>Loading...</div>;
return <div>Hello {data.name}!</div>;
}Combining SSR and CSR
You don't have to choose just one strategy! A common pattern is to render the outer skeleton or critical metadata of a page using SSR (for SEO), and then fetch the heavy or highly dynamic interior data using CSR on the client.
Next up, let's explore how we actually create that /api/user endpoint using API Routes.