Server Components

Back

Loading concept...

🚀 Server Components: The Kitchen That Cooks Before You Arrive

The Big Idea

Imagine you’re going to a restaurant. In a normal restaurant, you sit down, order food, and the chef starts cooking. You wait. And wait. Finally, your food arrives.

But what if there was a magical restaurant where the chef ALREADY knows what you want and starts cooking BEFORE you even walk in? When you arrive, your food is ready! 🍕

That’s React Server Components!

Server Components are React components that cook (run) on the server BEFORE they reach your phone or computer. They do all the hard work first, then send you the finished meal—not the recipe.


🧑‍🍳 Server Components Basics

What Are Server Components?

Think of your React app like a restaurant with two kitchens:

  1. The Back Kitchen (Server) — Hidden from customers. Big ovens, lots of ingredients, powerful equipment.
  2. The Front Kitchen (Client/Browser) — Small, in front of customers. Quick tasks only.

Server Components cook in the back kitchen. They:

  • Can reach into the fridge (database) directly
  • Use the big industrial oven (server power)
  • Send you the finished dish, not raw ingredients
// This runs on the SERVER
async function RecipeList() {
  // Get recipes from database
  const recipes = await db.query(
    'SELECT * FROM recipes'
  );

  return (
    <ul>
      {recipes.map(r => (
        <li key={r.id}>{r.name}</li>
      ))}
    </ul>
  );
}

Why is this amazing?

Old Way (Client) New Way (Server)
Send database code to browser Database stays secret
User downloads everything User gets ready HTML
Slow on old phones Fast everywhere

The Default is Server

In Next.js 13+ with App Router, every component is a Server Component by default. No special setup needed!

It’s like the restaurant assuming all dishes should be prepared in the back kitchen—unless you specifically ask for tableside cooking.


🆚 Client vs Server Components

The Two Worlds

graph TD A["Your React App"] --> B["Server Components"] A --> C["Client Components"] B --> D["Run on Server First"] B --> E["Can Access Database"] B --> F["Zero JavaScript to Browser"] C --> G["Run in Browser"] C --> H["Handle Clicks &amp; Typing"] C --> I["Use useState/useEffect"]

When to Use Each?

Think about WHO needs to do the work:

🖥️ Server Components (back kitchen):

  • Reading from database
  • Checking passwords
  • Getting data from APIs
  • Showing content that doesn’t change with clicks

📱 Client Components (front kitchen):

  • Button clicks
  • Form typing
  • Animations
  • Anything with useState or useEffect

Simple Example

Server Component (getting a user’s name):

// Runs on server - no 'use client'
async function UserGreeting() {
  const user = await getUser();
  return <h1>Hello, {user.name}!</h1>;
}

Client Component (counting button clicks):

'use client'  // ← This tells React!

import { useState } from 'react';

function LikeButton() {
  const [likes, setLikes] = useState(0);
  return (
    <button onClick={() => setLikes(likes + 1)}>
      ❤️ {likes}
    </button>
  );
}

The Golden Rule

If your component needs useState, useEffect, onClick, or any browser-only thing → it’s a Client Component.

Everything else → stays as Server Component (the default).


📝 The “use client” Directive

What Is It?

'use client' is like a sign on a restaurant table that says “Cook this dish tableside!”

It tells React: “Hey! This component and everything it imports needs to run in the browser.”

How to Use It

Put 'use client' at the very top of your file. Before imports. Before everything.

'use client'  // ← Must be FIRST LINE

import { useState } from 'react';
import { motion } from 'framer-motion';

function FancyButton() {
  const [clicked, setClicked] = useState(false);

  return (
    <motion.button
      onClick={() => setClicked(true)}
      animate={{ scale: clicked ? 1.2 : 1 }}
    >
      Click me!
    </motion.button>
  );
}

The Boundary Rule

When you add 'use client' to a file, it creates a boundary:

graph TD A["ServerPage"] --> B["ServerHeader"] A --> C["&&#35;39;use client&&#35;39; InteractiveForm"] C --> D["All children are Client too"] D --> E["InputField"] D --> F["SubmitButton"]

Everything inside a Client Component also becomes Client—like how everyone at a tableside cooking table shares the same cooking zone.

Common Mistakes

Wrong: Adding 'use client' to a page that just shows text

'use client'  // Unnecessary!

function AboutPage() {
  return <p>We sell cookies.</p>;
}

Right: Only use it when you need browser features

'use client'

import { useState } from 'react';

function CookieCounter() {
  const [count, setCount] = useState(0);
  return (
    <button onClick={() => setCount(count + 1)}>
      Cookies eaten: {count}
    </button>
  );
}

⏳ Async Components

The Superpower of Server Components

Here’s something magical: Server Components can be async!

This means they can await data before rendering. No useEffect. No loading states in the component. Just… wait for the data, then show it.

// This is ASYNC - note the async keyword
async function MovieList() {
  // Wait for movies from API
  const movies = await fetch(
    'https://api.movies.com/popular'
  ).then(r => r.json());

  return (
    <ul>
      {movies.map(movie => (
        <li key={movie.id}>
          🎬 {movie.title}
        </li>
      ))}
    </ul>
  );
}

Why Is This Amazing?

In the old Client Component world, getting data was messy:

// OLD WAY - Client Component 😓
'use client'
function MovieList() {
  const [movies, setMovies] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetch('https://api.movies.com/popular')
      .then(r => r.json())
      .then(data => {
        setMovies(data);
        setLoading(false);
      });
  }, []);

  if (loading) return <p>Loading...</p>;

  return (
    <ul>
      {movies.map(movie => (
        <li key={movie.id}>{movie.title}</li>
      ))}
    </ul>
  );
}

Compare that to the Server Component way! So much cleaner.

Multiple Awaits

You can await multiple things:

async function Dashboard() {
  const user = await getUser();
  const orders = await getOrders(user.id);
  const recommendations = await getRecommendations(user.id);

  return (
    <div>
      <h1>Welcome, {user.name}!</h1>
      <OrderList orders={orders} />
      <Recommendations items={recommendations} />
    </div>
  );
}

The Catch: Client Components Can’t Be Async

⚠️ Remember: Only Server Components can be async.

If you try this, it won’t work:

'use client'

// ❌ ERROR! Client components can't be async
async function BrokenComponent() {
  const data = await fetchData();
  return <div>{data}</div>;
}

For Client Components, you still need useEffect or libraries like React Query.


🎯 Putting It All Together

Let’s build a mini app that uses everything we learned:

// app/page.js (Server Component by default)

import LikeButton from './LikeButton';

async function BlogPost() {
  // Fetch on server
  const post = await fetch(
    'https://api.blog.com/latest'
  ).then(r => r.json());

  return (
    <article>
      <h1>{post.title}</h1>
      <p>{post.content}</p>

      {/* Client Component for interactivity */}
      <LikeButton postId={post.id} />
    </article>
  );
}

export default BlogPost;
// app/LikeButton.js
'use client'

import { useState } from 'react';

export default function LikeButton({ postId }) {
  const [liked, setLiked] = useState(false);

  return (
    <button
      onClick={() => setLiked(!liked)}
    >
      {liked ? '❤️ Liked!' : '🤍 Like'}
    </button>
  );
}

What happens:

  1. Server fetches the blog post (fast, no loading spinner)
  2. Server sends HTML with the post already filled in
  3. Browser receives ready-to-show content
  4. Only the tiny LikeButton JavaScript is sent
  5. User sees content instantly, can click like button

🎉 You Did It!

You now understand React Server Components! Here’s what you learned:

Concept What It Means
Server Components React that runs on the server first
Client vs Server Server = data/secrets, Client = clicks/animations
‘use client’ The magic words to make a Client Component
Async Components Server Components that await data directly

Quick Memory Trick

🍕 Pizza Analogy:

  • Server Components = Pre-made pizza (arrives hot and ready)
  • Client Components = Make-your-own pizza station (you do the work)
  • 'use client' = The sign that says “DIY station this way →”
  • Async = The chef who waits for fresh ingredients before cooking

Go build something amazing! 🚀

Loading story...

Story - Premium Content

Please sign in to view this story and start learning.

Upgrade to Premium to unlock full access to all stories.

Stay Tuned!

Story is coming soon.

Story Preview

Story - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.