Capítulo 22 de 35

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:

  1. Destruir a Performance: O navegador terá que fazer o download do Javascript de toda a página antes de mostrar qualquer coisa interativa.
  2. Matar o SEO: Robôs do Google terão dificuldade de ler meta-tags dinâmicas e o conteúdo inicial.
  3. 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.