React Server Components
Render components on the server for better performance
🖥️ What are Server Components?
Server Components render on the server and send HTML to the client, reducing JavaScript bundle size and improving performance. They can access backend resources directly without APIs, making data fetching simpler and faster.
// Server Component (default in Next.js 13+)
async function UserProfile() {
const user = await fetchUser();
return <div>{user.name}</div>;
}
Key Concepts
Zero Bundle
No JavaScript sent to client
Backend Access
Direct database queries
Performance
Faster initial page load
SEO Friendly
Fully rendered HTML
🔹 Server vs Client Components
Understanding the difference between server and client components is crucial. Server components run only on the server, while client components run in the browser and can use hooks and interactivity.
// ✅ Server Component (default)
async function BlogPost({ id }) {
// Can access database directly
const post = await db.posts.findById(id);
return (
<article>
<h1>{post.title}</h1>
<p>{post.content}</p>
</article>
);
}
// ✅ Client Component (needs 'use client')
'use client';
import { useState } from 'react';
function LikeButton() {
const [likes, setLikes] = useState(0);
return (
<button onClick={() => setLikes(likes + 1)}>
Likes: {likes}
</button>
);
}
Key Difference:
Server: No hooks, async/await, direct DB access
Client: Hooks, events, browser APIs
🔹 Data Fetching in Server Components
Server components can fetch data directly without useEffect or state management. They run on the server, so you can access databases, file systems, and APIs securely without exposing credentials.
// Server Component with data fetching
async function UserList() {
// Fetch data directly on server
const response = await fetch('https://api.example.com/users');
const users = await response.json();
return (
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}
// No loading states needed!
// No useEffect needed!
// No useState needed!
Output:
- John Doe
- Jane Smith
- Bob Johnson
🔹 Mixing Server and Client Components
Combine server and client components for optimal performance. Use server components for data fetching and static content, client components for interactivity:
// Server Component (page.jsx)
import ClientButton from './ClientButton';
async function ProductPage({ id }) {
// Fetch on server
const product = await fetchProduct(id);
return (
<div>
{/* Server-rendered content */}
<h1>{product.name}</h1>
<p>{product.description}</p>
<p>Price: ${product.price}</p>
{/* Client component for interactivity */}
<ClientButton productId={id} />
</div>
);
}
// Client Component (ClientButton.jsx)
'use client';
import { useState } from 'react';
export default function ClientButton({ productId }) {
const [added, setAdded] = useState(false);
return (
<button onClick={() => setAdded(true)}>
{added ? 'Added!' : 'Add to Cart'}
</button>
);
}
🔹 Benefits of Server Components
Performance Benefits:
- Smaller Bundle: Server code doesn't go to client
- Faster Load: Less JavaScript to download
- Better SEO: Fully rendered HTML
- Instant Data: No loading spinners needed
Developer Benefits:
- Direct Access: Query databases directly
- Simpler Code: No useEffect for data fetching
- Secure: Keep API keys on server
- Automatic: Works by default in Next.js 13+
🔹 When to Use Each Type
// ✅ Use Server Components for:
// - Data fetching
// - Accessing backend resources
// - Static content
// - SEO-critical content
async function BlogList() {
const posts = await db.posts.findAll();
return <PostList posts={posts} />;
}
// ✅ Use Client Components for:
// - Interactivity (onClick, onChange)
// - State management (useState, useReducer)
// - Browser APIs (localStorage, window)
// - React hooks (useEffect, useContext)
'use client';
function SearchBar() {
const [query, setQuery] = useState('');
return <input value={query} onChange={e => setQuery(e.target.value)} />;
}
🔹 Best Practices
✅ Do:
- Use server components by default
- Add 'use client' only when needed
- Fetch data in server components
- Keep client components small
❌ Don't:
- Use 'use client' everywhere
- Fetch data in client components unnecessarily
- Import server components into client components
- Use hooks in server components