React Server Components explicados: use client, Server Actions, Suspense | We.Inc
React Server Components em linguagem simples: um diagrama de fronteiras, as regras do "use client", busca de dados, server actions para formulários com useActionState, streaming com Suspense e soluções para erros comuns.
React Server Components explicados
React Server Components renderizam no servidor e enviam ao navegador a interface pronta, não o JavaScript deles. Eles podem fazer await de dados e usar segredos diretamente. Tudo o que é interativo fica em um Client Component, um arquivo que começa com "use client". Formulários podem chamar server functions marcadas com "use server", e o Suspense faz o streaming das partes lentas depois.
As três diretivas e hooks de que você precisa
Escreva
Significa
(nada)
Server Component, no App Router do Next.js
"use client"
Este arquivo e seus imports também rodam no navegador
"use server"
Estas funções exportadas rodam no servidor quando chamadas
<Suspense>
Mostra um fallback aqui enquanto esta parte carrega
Comece pelo diagrama: as caixas azuis ficam no servidor, as laranja também vão para o navegador. Depois copie os padrões de dados, formulários e streaming, e use a tabela de erros quando o build reclamar.
Deixe os componentes como Server Components por padrão.
Busque dados em Server Components async, perto de onde eles são exibidos.
Adicione "use client" só nas partes pequenas que precisam de estado ou handlers.
Use server functions para formulários e mutações, com useActionState para dar retorno.
Envolva as partes lentas em Suspense, ou adicione um loading.tsx, para a página aparecer rápido.
Empurre o "use client" o mais para baixo possível na árvore; uma fronteira perto da raiz deixa o app inteiro do lado do cliente de novo.
Valide toda entrada de server function. Ela é um endpoint público, mesmo que só o seu formulário a chame.
Verifique quem é o usuário dentro de cada server function, não só na página que mostra o formulário.
Passe Server Components para Client Components como children em vez de importá-los.
Evite cascatas de requisições: inicie buscas independentes juntas com Promise.all.
Perguntas frequentes
Server Components são a mesma coisa que renderização no servidor?
Não. A renderização no servidor transforma qualquer componente em HTML no primeiro carregamento e ainda envia o JavaScript dele. Um Server Component nunca envia o próprio JavaScript; só o resultado vai. Client Components continuam sendo renderizados no servidor no primeiro carregamento.
Preciso de Next.js para usar Server Components?
Eles precisam de um framework ou bundler que dê suporte. O App Router do Next.js é o mais usado; alguns outros, como o Waku, também dão suporte.
Um Client Component pode importar um Server Component?
Não, um import a partir de um arquivo de cliente puxa o módulo para o bundle do cliente. Em vez disso, passe o Server Component como children ou outra prop a partir de um pai que seja Server Component.
Qual a diferença entre server actions e server functions?
Hoje o React chama qualquer função marcada com "use server" de server function. Quando ela é usada como action de formulário ou chamada dentro de uma transition, costuma ser chamada de server action. O Next.js usou o termo server actions primeiro.
O useActionState funciona sem JavaScript?
O formulário continua enviando para a server function antes da hydration, então o envio funciona. O estado pendente e a mensagem na página precisam de JavaScript, então garanta que o servidor retorne uma página útil nos dois casos.
Por que esse modelo ajuda um site
A maior parte de uma página de marketing ou de conteúdo nunca muda depois de renderizada: títulos, texto, imagens, cards de produto. Como Server Components, elas não custam nada de JavaScript, o que deixa a main thread livre para as poucas partes interativas e normalmente melhora o Interaction to Next Paint.
Checklist de segurança para server functions
Trate cada função "use server" como uma rota de API: verifique a sessão, valide a entrada com um schema, confira se o usuário pode alterar aquele registro e retorne só o que o cliente precisa. Nunca retorne linhas do banco com campos que o usuário não deveria ver.
O que roda onde
Onde cada coisa pode rodar
Você precisa
Server Component
Client Component
Ler um banco de dados ou uma chave de API secreta
Sim
Não (exporia o segredo)
Fazer await de dados direto no componente
Sim (componente async)
Não
useState, useEffect, useReducer
Não
Sim
onClick, onChange e outros handlers
Não
Sim
window, localStorage, APIs do navegador
Não
Sim, depois do mount
Enviar zero JavaScript para o componente
Sim
Não
Renderizar o outro tipo
Sim, renderiza Client Components
Só Server Components recebidos como children ou props
Server Components e Client Components
Um Server Component que lê dados
No App Router, os componentes são Server Components a menos que sejam marcados de outra forma. Eles podem ser async e falar direto com o banco; nada desse código chega ao navegador.
Um Client Component para interação
"use client" logo no topo marca uma fronteira: este arquivo e tudo o que ele importa vão para o bundle do navegador. Mantenha esses arquivos pequenos e empurre-os para as folhas da árvore.
Passando um Server Component por um Client Component
Um Client Component não pode importar um Server Component, mas pode recebê-lo como children. O servidor renderiza primeiro e o cliente só posiciona o resultado.
Evite mandar segredos para o navegador por acidente
Importar o pacote server-only faz o build falhar se algum arquivo de cliente importar este módulo, então uma chave de API não vaza por um import descuidado.
Server functions para formulários
Um formulário que envia para uma server function
"use server" transforma uma função async em um endpoint que o formulário pode chamar. O formulário funciona antes de o JavaScript carregar, porque é um envio de formulário de verdade.
Estado pendente e de resultado com useActionState
useActionState (React 19) envolve a server function e devolve o último resultado e uma flag de pendente, então o botão pode dizer Enviando e a mensagem pode aparecer sem estado extra.
Atualize os dados da página depois de uma mudança
Depois de uma mutação, diga ao Next.js quais dados de qual caminho estão desatualizados para que o próximo render mostre a mudança.
Streaming com Suspense
Faça streaming da parte lenta com Suspense
Envolva um Server Component lento em Suspense. O resto da página é enviado de uma vez com o fallback no lugar, e a parte lenta chega por streaming quando os dados dela ficam prontos.
loading.tsx para uma rota inteira
Um arquivo loading.tsx ao lado do page.tsx envolve essa página em uma fronteira de Suspense para você, então a navegação o mostra na hora enquanto os dados da página carregam.
Inicie as requisições juntas
Fazer await de uma busca depois da outra em um Server Component soma os tempos delas. Inicie as duas ao mesmo tempo e faça await das duas.
Erros que você vai encontrar
Erros comuns e a solução
O que você vê
Causa
Solução
Um hook como useState só funciona em um Client Component
Um hook em um arquivo sem "use client"
Mova a parte interativa para um arquivo próprio que comece com "use client"
Event handlers não podem ser passados para props de Client Component
onClick passado a partir de um Server Component
Coloque o handler dentro do Client Component ou passe uma server function
Funções não podem ser passadas diretamente para Client Components
Uma função comum passada como prop através da fronteira
Marque-a com "use server" se ela deve rodar no servidor, ou defina-a no arquivo de cliente
Só objetos simples podem ser passados para Client Components
Instâncias de classe, como models cheios de Date ou Maps, enviadas como props
Passe dados simples (strings, números, arrays, objetos simples)
window is not defined
API do navegador usada durante a renderização no servidor
Leia dentro do useEffect ou verifique typeof window antes
Hydration mismatch
Servidor e navegador renderizaram textos diferentes (datas, valores aleatórios)
Renderize a parte que muda só no cliente ou passe o valor a partir do servidor