What are React Server Components (RSC)?

👨‍💻 Frontend Developer 🟠 May come up 🎚️ Hard
#React #Next.js #SSR

Brief Answer

React Server Components (RSC) is a new React architecture that allows components to run on the server:

  1. Server Components — run on the server 🖥️
  2. Client Components — run in the browser 🌐
  3. Zero JavaScript — server components don’t send JS to browser 📦
  4. Direct data access — can access database directly 🗄️
  5. Automatic code splitting — bundle optimization ⚡
  6. Streaming — progressive content loading 🌊
// Server Component
async function ServerComponent() {
  const data = await fetch('api/data');
  return <div>{data.title}</div>;
}
 
// Client Component
'use client';
function ClientComponent() {
  const [count, setCount] = useState(0);
  return <button onClick={() => setCount(count + 1)}>{count}</button>;
}

Full Answer

React Server Components is a revolutionary architecture that changes how we build React applications! They allow components to run on the server, providing numerous benefits. 🚀

Core Concepts

1. Server Components

Run on the server and send ready HTML:

// app/posts/page.js
async function PostsPage() {
  // Runs on server
  const posts = await db.posts.findMany();
  
  return (
    <div>
      <h1>Posts</h1>
      {posts.map(post => (
        <article key={post.id}>
          <h2>{post.title}</h2>
          <p>{post.content}</p>
        </article>
      ))}
    </div>
  );
}

2. Client Components

Run in browser with interactivity:

// components/LikeButton.js
'use client';
import { useState } from 'react';
 
function LikeButton({ postId }) {
  const [liked, setLiked] = useState(false);
  
  return (
    <button 
      onClick={() => setLiked(!liked)}
      className={liked ? 'liked' : ''}
    >
      {liked ? '❤️' : '🤍'} Like
    </button>
  );
}

RSC Architecture

// Server Component (default)
async function BlogPost({ id }) {
  const post = await getPost(id);
  
  return (
    <article>
      <h1>{post.title}</h1>
      <p>{post.content}</p>
      
      {/* Client component for interactivity */}
      <LikeButton postId={id} />
      <Comments postId={id} />
    </article>
  );
}
 
// Client Component
'use client';
function Comments({ postId }) {
  const [comments, setComments] = useState([]);
  
  useEffect(() => {
    loadComments(postId).then(setComments);
  }, [postId]);
  
  return (
    <div>
      {comments.map(comment => (
        <div key={comment.id}>{comment.text}</div>
      ))}
    </div>
  );
}

RSC Benefits

1. Performance

// Server Component - 0 KB JavaScript
function ProductList() {
  const products = await db.products.findMany();
  return (
    <div>
      {products.map(product => (
        <ProductCard key={product.id} product={product} />
      ))}
    </div>
  );
}
 
// Only interactive parts sent to browser
'use client';
function AddToCart({ productId }) {
  return (
    <button onClick={() => addToCart(productId)}>
      Add to Cart
    </button>
  );
}

2. Security

// Server Component - secret keys stay on server
async function UserProfile({ userId }) {
  const user = await db.users.findUnique({
    where: { id: userId },
    select: { name: true, email: true } // Don't send password
  });
  
  return <div>Hello, {user.name}!</div>;
}

3. SEO and accessibility

// Server Component - ready HTML for search engines
async function ArticlePage({ slug }) {
  const article = await getArticle(slug);
  
  return (
    <>
      <Head>
        <title>{article.title}</title>
        <meta name="description" content={article.excerpt} />
      </Head>
      <article>
        <h1>{article.title}</h1>
        <div dangerouslySetInnerHTML={{ __html: article.content }} />
      </article>
    </>
  );
}

Streaming and Suspense

// app/dashboard/page.js
import { Suspense } from 'react';
 
function Dashboard() {
  return (
    <div>
      <h1>Dashboard</h1>
      
      <Suspense fallback={<div>Loading stats...</div>}>
        <Stats />
      </Suspense>
      
      <Suspense fallback={<div>Loading charts...</div>}>
        <Charts />
      </Suspense>
    </div>
  );
}
 
// Slow server component
async function Stats() {
  const stats = await getStats(); // Slow query
  return <div>Stats: {stats.total}</div>;
}

Data Passing Between Components

// Server component passes data to client component
async function PostPage({ params }) {
  const post = await getPost(params.id);
  const user = await getCurrentUser();
  
  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.content}</p>
      
      {/* Pass data to client component */}
      <InteractiveSection 
        postId={post.id}
        userId={user.id}
        initialLikes={post.likes}
      />
    </div>
  );
}
 
'use client';
function InteractiveSection({ postId, userId, initialLikes }) {
  const [likes, setLikes] = useState(initialLikes);
  
  return (
    <div>
      <button onClick={() => setLikes(likes + 1)}>
        👍 {likes}
      </button>
    </div>
  );
}

RSC Limitations

Server Components CANNOT:

// ❌ Use state hooks
function ServerComponent() {
  const [state, setState] = useState(0); // Error!
  return <div>{state}</div>;
}
 
// ❌ Use effects
function ServerComponent() {
  useEffect(() => {}, []); // Error!
  return <div>Content</div>;
}
 
// ❌ Use browser APIs
function ServerComponent() {
  const width = window.innerWidth; // Error!
  return <div>Width: {width}</div>;
}

Client Components CANNOT:

// ❌ Import server modules
'use client';
import { db } from './database'; // Error!
 
function ClientComponent() {
  return <div>Client</div>;
}

Best Practices

  1. Use server components by default 🖥️
  2. Client components only for interactivity 🎯
  3. Pass data through props 📤
  4. Use Suspense for loading
// ✅ Correct architecture
async function ProductPage({ id }) {
  const product = await getProduct(id); // Server
  
  return (
    <div>
      <ProductInfo product={product} /> {/* Server */}
      <AddToCartButton productId={id} /> {/* Client */}
    </div>
  );
}

Common Mistakes

Wrong:

// Mixing server and client code
function Component() {
  const [state, setState] = useState(0);
  const data = await fetch('/api'); // Error!
  return <div>{data}</div>;
}

Correct:

// Separation of concerns
async function ServerComponent() {
  const data = await fetch('/api');
  return <ClientComponent initialData={data} />;
}
 
'use client';
function ClientComponent({ initialData }) {
  const [state, setState] = useState(0);
  return <div>{initialData.title}</div>;
}

Conclusion

React Server Components is the future of React development:

  • Better performance — less JavaScript in browser
  • Improved SEO — ready HTML content
  • Security — server logic stays on server
  • Streaming — fast content loading

Use RSC to build fast and efficient applications! 🚀