Limites Arquiteturais: React Server Components vs Client Components
A Revolução do App Router
No passado, o React enviava todo o código Javascript da sua interface para o navegador do cliente, que precisava fazer o download, processar e só então desenhar a tela (Client-Side Rendering). Isso gerava telas brancas, lentidão em celulares antigos e péssimo ranqueamento no Google (SEO).
Com a chegada do Next.js App Router e dos React Server Components (RSC), o jogo virou: por padrão, todo componente React agora roda e morre no servidor da Vercel. O cliente recebe apenas o HTML puro e ultraleve.
O Anti-Pattern do "use client" na Raiz
O maior erro de arquitetura moderno (e o vício mais comum de IAs geradoras de código) acontece quando o desenvolvedor tenta usar um estado (useState) ou um efeito (useEffect) na página principal (page.tsx).
O Next.js bloqueia a compilação e avisa que Hooks só funcionam no cliente. A solução preguiçosa? Injetar a diretiva "use client" na linha 1 do arquivo page.tsx.
Por que isso destrói a sua arquitetura?
Quando você coloca "use client" na raiz da página, tudo que estiver abaixo daquele componente também se torna Client Component. Você acabou de:
- Destruir a Performance: O navegador terá que fazer o download do Javascript de toda a página antes de mostrar qualquer coisa interativa.
- Matar o SEO: Robôs do Google terão dificuldade de ler meta-tags dinâmicas e o conteúdo inicial.
- Criar Falhas de Segurança: Chaves de API de banco de dados que deveriam ser secretas podem acabar expostas no bundle do navegador.
A Regra de Ouro: Empurre a Interatividade para as Bordas
A arquitetura correta exige que a sua aplicação seja 90% Server Component (Renderizando o layout, lendo o banco de dados e montando o HTML) e apenas 10% Client Component nas folhas da árvore (os botões e formulários).
❌ Arquitetura Amadora (Proibida)
// app/dashboard/page.tsx
"use client" // ERRO FATAL: Destruiu o SSR da página inteira
import { useState } from 'react'
import { buscarDadosPesadosNoBanco } from '@/lib/db' // Perigo de segurança!
export default function DashboardPage() {
const [modalAberto, setModalAberto] = useState(false)
const dados = buscarDadosPesadosNoBanco()
return (
<main>
<h1>Dashboard Privado</h1>
<p>{dados}</p>
<button onClick={() => setModalAberto(true)}>Abrir Menu</button>
</main>
)
}
✅ Arquitetura Corporativa (Padrão Ouro)
O arquivo da página (page.tsx) permanece como Server Component. A interatividade é isolada em um micro-componente cliente separado.
1. O Componente Servidor (A Raiz):
// app/dashboard/page.tsx
// NADA DE "use client" AQUI! É executado no Servidor.
import { buscarDadosPesadosNoBanco } from '@/lib/db' // 100% seguro
import BotaoMenu from './BotaoMenu' // Importamos apenas a interatividade
export default async function DashboardPage() {
const dados = await buscarDadosPesadosNoBanco()
return (
<main>
<h1>Dashboard Privado</h1>
<p>{dados}</p>
{/* O componente cliente é injetado aqui */}
<BotaoMenu />
</main>
)
}
2. O Componente Cliente (A Folha):
// app/dashboard/BotaoMenu.tsx
"use client" // A diretiva fica isolada APENAS onde há interatividade
import { useState } from 'react'
export default function BotaoMenu() {
const [modalAberto, setModalAberto] = useState(false)
return <button onClick={() => setModalAberto(true)}>Abrir Menu</button>
}
Conclusão
Sempre que precisar de interatividade (clicks, states, efeitos, manipulação do DOM), isole esse comportamento em um componente pequeno e jogue o "use client" nele.
Mantenha as páginas, layouts e componentes pesados rodando em segurança no servidor. Essa disciplina separa as aplicações lentas de tutorial das arquiteturas velozes de alta disponibilidade.