React Server Components (RSC)
O que são RSC, quando usar Server vs Client Components, e como pensar a fronteira.
Definição
React Server Components rodam exclusivamente no servidor: sem hydration, sem JS enviado ao cliente, acesso direto a banco/filesystem/variáveis de ambiente. Client Components ('use client') têm interatividade, hooks de estado e efeitos. No Next.js App Router, todos os componentes são Server por padrão. A fronteira server/client é onde você adiciona 'use client'.
Problema → Solução
Problema
Marcar tudo como 'use client' por hábito derrota o propósito dos RSC. Ou o oposto: tentar usar useState em Server Components e não entender o erro.Solução
Regra: mova 'use client' para as folhas da árvore. Componentes de layout, listas, tabelas — Server. Componentes com interação (formulários, toggles, modais) — Client. Server Components podem passar dados como props para Client Components, mas não o contrário.Dica de entrevista
Tip
Server Components não têm: useState, useEffect, event handlers, Browser APIs. Client Components têm tudo isso. Dúvida: o componente precisa reagir a input do usuário ou mudança de estado no browser? 'use client'. Só renderiza dados estáticos? Server.Código
// ✅ Server Component — sem JS no cliente, fetch direto
// app/products/page.tsx (Server Component por default)
async function ProductsPage() {
// Acesso direto ao banco — sem API, sem useEffect
const products = await db.product.findMany({ where: { active: true } })
return (
<main>
<h1>Produtos</h1>
{/* ProductCard é Server Component — zero hydration */}
{products.map(p => <ProductCard key={p.id} product={p} />)}
{/* AddToCartButton precisa de estado — é Client */}
<AddToCartButton productId={products[0].id} />
</main>
)
}
// ✅ Client Component na folha da árvore
// components/AddToCartButton.tsx
'use client'
import { useState } from 'react'
export function AddToCartButton({ productId }: { productId: string }) {
const [added, setAdded] = useState(false)
return (
<button onClick={() => {
addToCart(productId)
setAdded(true)
}}>
{added ? '✓ Adicionado' : 'Adicionar ao carrinho'}
</button>
)
}
// ✅ Passando Server Component como children para Client
function ClientLayout({ children }: { children: React.ReactNode }) {
'use client'
const [open, setOpen] = useState(false)
return <div>{open && children}</div>
}
// children pode ser um Server Component!Perguntas de entrevista
Q.Qual a vantagem real dos Server Components?▾
A.Zero JS enviado ao cliente para componentes puramente de apresentação. Acesso direto a banco sem API intermediária. Fetch de dados no servidor = sem loading state, sem useEffect, sem race conditions. Secrets do servidor nunca expostos. Bundle menor = melhor performance.
Q.Posso importar um Server Component dentro de um 'use client'?▾
A.Não diretamente — o boundary 'use client' transforma tudo abaixo em client. Mas você pode passar Server Components como children ou props para Client Components: `<ClientWrapper>{children}</ClientWrapper>` onde children é um Server Component. O padrão correto é passar como prop, não importar.
Q.Como fazer fetch de dados em RSC?▾
A.Diretamente no componente com async/await — Server Components podem ser async: `async function Page() { const data = await db.query(...); return <List data={data} /> }`. No Next.js, o fetch é automaticamente deduplicado e cacheado. Para revalidação: `fetch(url, { next: { revalidate: 60 } })` ou `revalidatePath()`.
Termos relacionados
82/122← →