- Sloth Bytes
- Posts
- 🦥 React Server Components For Dummies
🦥 React Server Components For Dummies
Hello friends!
Welcome to this week’s Sloth Bytes. I hope you had an amazing week!
Latest Posts
If you’re new, or not yet a subscriber, or just plain missed it, here are some of our recent editions:

Personalized Onboarding for Every User
Quarterzip makes user onboarding seamless and adaptive. No code required.
✨ Analytics and insights track onboarding progress, sentiment, and revenue opportunities
✨ Branding and personalization match the assistant’s look, tone, and language to your brand.
✨ Guardrails keep things accurate with smooth handoffs if needed
Onboarding that’s personalized, measurable, and built to grow with you.

React Server Components
In 2022 React introduced this thing called Server Components, and now they’ve become the standard if you’re working on a Next.js project or a project that uses React 18+.
Now I’m not the brightest person, so it took me a minute to understand how it worked and why they made it.
Here’s how React defines them in their documentation:
Server Components are a new option that allows rendering components ahead of time, before bundling, in an environment separate from your client application or SSR server.
Makes sense right?
Here’s a super simplified definition: Components that run only on the server.
You’re welcome 😎
Basically React is finally catching up to PHP…
The Problem With React
Let's say you're building a blog and working on the page with all the blog posts (/blogs).
You need to fetch the posts from a database and display them.
Before Server Components, there were 3 main options for handling this:
Option 1: Client Side Rendering (CSR)
function BlogPosts() {
const [posts, setPosts] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch('/api/posts')
.then(res => res.json())
.then(data => {
setPosts(data);
setLoading(false);
});
}, []);
if (loading) return <div>Loading...</div>;
return <div>{posts.map(post => <PostCard key={post.id} post={post} />)}</div>;
}
This is traditional React.
The code itself isn't that bad, but here's what happens when you run it:
Browser gets empty HTML
Browser downloads entire React bundle
React boots up, renders nothing
useEffect fires, fetches data
Data returns, component re-renders
User finally sees something
Problems with it: Huge JS bundle, blank screen first, terrible SEO, all dependencies ship to browser.
Option 2: Server-Side Rendering (SSR - Next.js example)
For these other options I’ll be using next.js since it’s more popular.
// Next.js 12
export async function getServerSideProps() {
const posts = await db.posts.findMany();
return { props: { posts } };
}
function BlogPosts({ posts }) {
return <div>{posts.map(post => <PostCard key={post.id} post={post} />)}</div>;
}
Problems: User sees content faster (good!), but still ships all JavaScript for hydration, Your bundle size isn't reduced, every component becomes JavaScript so React can make it interactive.
Option 3: Static Site Generation (SSG)
Same code as SSR but with getStaticProps instead.
// Next.js 12 - only change is the function name
export async function getStaticProps() {
const posts = await db.posts.findMany();
return { props: { posts } };
}
Problems: Only works for static content, long build times, still ships all JavaScript, can't personalize per user.
What’s the problem?
Every component still ships to the browser as JavaScript for hydration. Even purely static ones like headers.
We can’t really combine these options at a component level, only at a page level.
What we really wanted: component-level control where only interactive components send JavaScript to the browser.
Server Components finally give us that.
What Server Components Actually Do
React Server Components allow individual components to stay on the server.
Here's the same blog with Server Components:
// app/blog/page.js - Server Component (default in Next.js 13+)
import { db } from '@/lib/database';
// async function now!
async function BlogPosts() {
// Direct database access - no API needed!
const posts = await db.posts.findMany();
return <div>{posts.map(post => <PostCard key={post.id} post={post} />)}</div>;
}
Notice what's missing: useState, useEffect, loading states, API routes.
Now we have:
Direct database access
No API route needed
Only HTML ships to the browser
Mixing Server and Client Components (The Real Power)
Now that we have the ability to decide at the component level, we can now mix server components AND client components.
Let’s say within the blog post we want an interactive like button.
// app/blog/[id]/page.js - Server Component
import { db } from '@/lib/database';
import LikeButton from '@/components/LikeButton';
async function BlogPost({ params }) {
const post = await db.posts.findUnique({ where: { id: params.id } });
return (
<article>
<h1>{post.title}</h1>
<LikeButton postId={post.id} initialLikes={post.likes} />
</article>
);
}
Before Server Components, the entire BlogPost would've been a client component just because of that one interactive button.
But now, only the LikeButton is a client component.
// components/LikeButton.js - Client Component
'use client';
import { useState } from 'react';
export default function LikeButton({ postId, initialLikes }) {
const [likes, setLikes] = useState(initialLikes);
const [isLiked, setIsLiked] = useState(false);
const handleLike = async () => {
if (isLiked) return;
setLikes(likes + 1);
setIsLiked(true);
await fetch(`/api/posts/${postId}/like`, { method: 'POST' });
};
return (
<button onClick={handleLike} disabled={isLiked}>
❤️ {likes} likes
</button>
);
}
What happens:
BlogPost runs on server, fetches from database
HTML generated with post content
Only the LikeButton JavaScript sent to browser
User sees content immediately and the button is interactive

Much better!
Server Components Vs Client Components
Use Server Components for:
Data fetching - Direct database access, no API routes needed
Heavy dependencies - Keep large libraries on the server
SEO content - Server Components generate HTML on the server, making content easily indexable
Static content - If it doesn't need useState or useEffect, keep it on the server
Use Client Components for:
Interactivity - Anything with onClick, onChange, or state management needs Client Components
Browser APIs - localStorage, geolocation, WebSockets only work in Client Components
Real-time updates - Server Components don't support WebSockets—use client-side fetching
React hooks - useState, useEffect, useContext = Client Component
Simple rule: Does it need to respond to user input or use browser features? Client Component. Otherwise? Server Component.
Trade-offs to Know
1. Client Components can only import other Client Components

Visual to help!
If you put a “use client” in a component, all other components within it have to be “use client” too.
No Context in Server Components - React Context isn't available in Server Components since they don't re-render. Fetch directly or pass props instead.
Trade HTML size for JS size - Your initial HTML payload is larger because it's pre-rendered, but you eliminate JavaScript that would otherwise need to be downloaded, parsed, and executed. Total bandwidth is usually lower, and HTML renders faster than JS anyway.
Learning curve - It takes a bit at first to understand which component is running where
Why It's Worth Learning
1. Real performance gains. Reduced bundle size and eliminated hydration improve Time to Interactive metrics.
2. Simpler data fetching. No useEffect waterfalls, no loading states everywhere, no API routes for every data fetch. Parallel fetching on server becomes easier.
3. It's the future. Next.js 13+ defaults to Server Components. React 19 stabilized the APIs. You'll encounter this soon if you're building React apps professionally.
4. Better architecture. The biggest shift is accepting not every component needs interactivity. This forces you to think about what actually needs client-side JavaScript.
Getting Started
The good news? Getting started is actually pretty simple.
Next.js does server components by default, so all you have to do is create a new Next project:
npx create-next-app@latest my-app
cd my-app
npm run devFour rules you should always remember:
All components are Server Components by default
Add "use client" only when you need interactivity or hooks
Keep data fetching at the top of your component tree
Don't overthink. If it doesn't work as Server, make it Client and move on
Build something simple first: a blog, docs site, or product catalog. You'll figure out the pattern quickly.

Thanks to everyone who submitted!
I don’t want the email to clip, so I’ll do the first 5 submissions this week (sorry!)
Thanksgiving week - no challenge!
It’s thanksgiving week here in the US (american btw), so I’ll give you a break (not because I’m lazy….)
That’s all from me!
Have a great week, be safe, make good choices, and have fun coding.
If I made a mistake or you have any questions, feel free to comment below or reply to the email!
See you all next week.
What'd you think of today's email? |
Want to advertise in Sloth Bytes?
If your company is interested in reaching an audience of developers and programming enthusiasts, you may want to advertise with us here.



Reply