O que é Client Component?
Client Component no Next.js (a partir da versão 13 com App Router) é um componente React que é renderizado e hidratado no navegador do cliente. Para declarar um Client Component, basta adicionar a diretiva 'use client' no topo do arquivo. Isso instrui o Next.js a incluir aquele componente e todas as suas dependências no bundle JavaScript enviado ao browser, permitindo o uso de hooks como useState, useEffect, useReducer e acesso a APIs do browser como window, document e localStorage.
A principal razão de existir essa distinção é a arquitetura de Server Components introduzida no React 18 e adotada pelo Next.js App Router. Por padrão, todo componente no diretório app/ é um Server Component — ele roda apenas no servidor, não aumenta o bundle do cliente e pode acessar diretamente banco de dados, sistema de arquivos e variáveis de ambiente sensíveis. O Client Component quebra esse paradigma quando você precisa de interatividade, estado local ou efeitos colaterais no browser.
Casos de uso reais incluem: formulários com validação em tempo real, modais e dropdowns controlados por estado, componentes que consomem Context API, integrações com bibliotecas de terceiros que dependem do DOM (como editores de texto rich text, mapas, bibliotecas de animação), e qualquer lógica que dependa de eventos do usuário (onClick, onChange, onSubmit). Uma pegadinha clássica é tentar usar useState ou useEffect em um Server Component — o Next.js lança um erro em build time ou runtime avisando que aquele hook não é suportado fora do contexto cliente.
Uma pegadinha crítica de arquitetura: a diretiva 'use client' define uma fronteira (boundary) na árvore de componentes. Todos os componentes importados dentro de um Client Component também se tornam parte do bundle do cliente, mesmo que não tenham a diretiva explicitamente. Por isso, o padrão recomendado é empurrar os Client Components para as folhas da árvore (leaf components), mantendo o máximo possível de lógica nos Server Components para reduzir o JavaScript enviado ao cliente. Outro erro comum é tentar passar funções não serializáveis (como callbacks arbitrários) como props de um Server Component para um Client Component — apenas dados serializáveis em JSON são permitidos nessa fronteira.
'use client';
import { useState, useEffect } from 'react';
interface Product {
id: number;
name: string;
price: number;
}
interface ProductCardProps {
product: Product;
onAddToCart: (id: number) => void;
}
export function ProductCard({ product, onAddToCart }: ProductCardProps) {
const [quantity, setQuantity] = useState(1);
const [addedFeedback, setAddedFeedback] = useState(false);
useEffect(() => {
if (addedFeedback) {
const timer = setTimeout(() => setAddedFeedback(false), 2000);
return () => clearTimeout(timer);
}
}, [addedFeedback]);
function handleAdd() {
onAddToCart(product.id);
setAddedFeedback(true);
}
return (
<div className="border rounded p-4">
<h2 className="text-lg font-bold">{product.name}</h2>
<p className="text-gray-600">R$ {product.price.toFixed(2)}</p>
<div className="flex items-center gap-2 mt-2">
<button onClick={() => setQuantity((q) => Math.max(1, q - 1))}>-</button>
<span>{quantity}</span>
<button onClick={() => setQuantity((q) => q + 1)}>+</button>
</div>
<button
onClick={handleAdd}
className="mt-3 bg-blue-600 text-white px-4 py-2 rounded"
>
{addedFeedback ? 'Adicionado!' : 'Adicionar ao carrinho'}
</button>
</div>
);
}Artigos que aprofundam Client Component
Quer ver Client Component em ação em projetos reais?
Ver artigos sobre Client Component