react-server-components

React Server Components

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "react-server-components" with this command: npx skills add claude-dev-suite/claude-dev-suite/claude-dev-suite-claude-dev-suite-react-server-components

React Server Components

Full Reference: See advanced.md for streaming patterns, caching strategies, advanced composition patterns, error handling, and parallel/sequential data fetching.

Deep Knowledge: Use mcp__documentation__fetch_docs with technology: react , topic: server-components for comprehensive documentation.

When NOT to Use This Skill

  • Building client-only apps (CRA, Vite)

  • Using Next.js Pages Router

  • React version < 18

  • Framework doesn't support RSC

Overview

┌─────────────────────────────────────────────────────────────────┐ │ Server │ ├─────────────────────────────────────────────────────────────────┤ │ Server Components │ │ • Run only on server │ │ • Can access databases, filesystems, secrets │ │ • Zero bundle size impact │ │ • No hooks (useState, useEffect) │ ├─────────────────────────────────────────────────────────────────┤ │ Client │ ├─────────────────────────────────────────────────────────────────┤ │ Client Components │ │ • Run on client (and server for SSR) │ │ • Can use hooks, event handlers │ │ • Interactive │ │ • Add to JS bundle │ └─────────────────────────────────────────────────────────────────┘

Server Components (Default in Next.js App Router)

// app/users/page.tsx - Server Component by default import { db } from '@/lib/db';

export default async function UsersPage() { // Direct database access - no API layer needed! const users = await db.user.findMany({ orderBy: { createdAt: 'desc' }, take: 10, });

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

Accessing Server-Only Resources

// app/dashboard/page.tsx import { cookies, headers } from 'next/headers';

export default async function DashboardPage() { const cookieStore = await cookies(); const token = cookieStore.get('session')?.value;

const user = await verifyToken(token); if (!user) { redirect('/login'); }

const stats = await db.stats.findUnique({ where: { userId: user.id }, });

return <Dashboard user={user} stats={stats} />; }

Client Components

Add 'use client' directive for interactivity:

// components/counter.tsx 'use client';

import { useState } from 'react';

export function Counter() { const [count, setCount] = useState(0);

return ( <button onClick={() => setCount(c => c + 1)}> Count: {count} </button> ); }

Composition: Server + Client

// app/products/page.tsx (Server Component) import { db } from '@/lib/db'; import { FilterSidebar } from '@/components/filter-sidebar';

export default async function ProductsPage({ searchParams }) { const products = await db.product.findMany({ where: { category: searchParams.category }, });

const categories = await db.category.findMany();

return ( <div className="flex"> {/* Client Component for interactivity /} <FilterSidebar categories={categories} /> {/ Server-rendered products */} <ProductGrid products={products} /> </div> ); }

Server Actions

Mutate data from client with server functions:

// app/actions.ts 'use server';

import { revalidatePath } from 'next/cache'; import { redirect } from 'next/navigation'; import { z } from 'zod';

const CreatePostSchema = z.object({ title: z.string().min(3).max(100), content: z.string().min(10), });

export async function createPost(formData: FormData) { const validated = CreatePostSchema.safeParse({ title: formData.get('title'), content: formData.get('content'), });

if (!validated.success) { return { error: validated.error.flatten().fieldErrors }; }

const user = await getCurrentUser(); if (!user) { return { error: { auth: ['Unauthorized'] } }; }

const post = await db.post.create({ data: { ...validated.data, authorId: user.id }, });

revalidatePath('/posts'); redirect(/posts/${post.id}); }

Using Server Actions

// Option 1: In a form export default function CreatePostPage() { return ( <form action={createPost}> <input name="title" required /> <textarea name="content" required /> <button type="submit">Create Post</button> </form> ); }

// Option 2: With useActionState for loading/error states 'use client';

import { useActionState } from 'react'; import { createPost } from '@/app/actions';

export function CreatePostForm() { const [state, formAction, isPending] = useActionState(createPost, null);

return ( <form action={formAction}> <input name="title" required /> {state?.error?.title && <p className="error">{state.error.title[0]}</p>} <button type="submit" disabled={isPending}> {isPending ? 'Creating...' : 'Create Post'} </button> </form> ); }

When to Use Server vs Client

Server Components Client Components

Data fetching Event handlers (onClick, onChange)

Database access useState, useEffect

Sensitive logic (secrets) Browser APIs

Heavy dependencies Interactivity

Static content Real-time updates

// Decision tree: // 1. Does it need interactivity? → Client // 2. Does it use hooks? → Client // 3. Does it need browser APIs? → Client // 4. Everything else → Server (default)

Anti-Patterns

Anti-Pattern Why It's Bad Correct Approach

Making everything Client Component Loses RSC benefits Default to Server, client only when needed

Passing functions to Client Components Not serializable Use Server Actions

Fetching data in Client Components Slower, larger bundle Fetch in Server Components

Not using Suspense Sequential loading Add Suspense boundaries

Exposing secrets in Client Security risk Keep in Server Components

Quick Troubleshooting

Issue Likely Cause Solution

"use client" not working Wrong file location Add to top of file

Cannot pass function as prop Functions not serializable Use Server Action

Hooks error in Server Component Using client hooks Add "use client" directive

Data not updating Cache not revalidated Use revalidatePath or revalidateTag

Slow data fetching Sequential fetches Use parallel Promise.all

Best Practices

  • ✅ Default to Server Components

  • ✅ Use 'use client' only when needed

  • ✅ Keep Client Components small and focused

  • ✅ Pass Server Components as children to Client

  • ✅ Use Suspense for streaming

  • ✅ Use Server Actions for mutations

  • ❌ Don't fetch data in Client Components if avoidable

  • ❌ Don't pass functions as props to Client Components

Reference Documentation

  • Server Components

  • Next.js App Router

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

cron-scheduling

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

token-optimization

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

webrtc

No summary provided by upstream source.

Repository SourceNeeds Review