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
React Server Components (RSC)
In Next.js 13+, the paradigm of how we write React apps completely changed with the introduction of React Server Components (RSC). Instead of sending massive amounts of JavaScript to the browser to render components, Next.js can now render components entirely on the Node.js Server and send only the finished HTML.
Server Components (Default)
By default, every component inside the app/ router is a Server Component. This means:
- No JavaScript is sent to the client for this component. This vastly reduces your bundle size and increases speed.
- Safe Secrets: You can write database queries and use API keys directly inside the component securely.
- No Hooks: Since it renders on a Node server, it has no concept of a browser! Therefore, you cannot use `useState`, `useEffect`, or DOM APIs like `window`.
// app/products/page.js
// This inherently ONLY runs on the server!
export default async function ProductsPage() {
const dbData = await sql`SELECT * FROM products`;
return (
<ul>
{dbData.map(item => <li key={item.id}>{item.name}</li>)}
</ul>
);
}Client Components (`'use client'`)
If your component requires user interaction (like a clicking a button to open a modal) or React state, it must be a Client Component. To opt-in simply place the 'use client' directive at the absolute top of the file.
'use client'; // This tells Next.js to ship JS to the browser for this file!
import { useState } from 'react';
export default function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
Clicked {count} times
</button>
);
}The Mixing Rule: Server inside Client
One of the trickiest rules for beginners: You can import a Client Component into a Server Component, but you CANNOT directly import a Server Component into a Client Component.If you do, the server component will be automatically converted to a client component!
However, you CAN pass a Server Component as {children} or as a prop to a Client Component.
// ❌ BAD:
'use client';
import ServerProfileData from './ServerProfileData'; // Will crash or force to client
// ✅ GOOD:
import ClientWrapper from './ClientWrapper';
import ServerProfileData from './ServerProfileData';
// Wrap them inside a Server Component:
export default function Page() {
return (
<ClientWrapper>
<ServerProfileData />
</ClientWrapper>
)
}Conclusion
By isolating interactivity into specific leaf Client Components, the rest of your app remains purely serverside. This makes your Next.js application unbelievably fast and SEO-perfect. But how do we submit forms securely on the server? That's where Server Actions come in!