React com Claude Code em produção: componentes, Hooks, testes e revisão
Use Claude Code no React com componentes tipados, Hooks, testes, acessibilidade, performance e revisão.
Claude Code acelera o desenvolvimento React, mas times de produção precisam de mais do que velocidade. O objetivo é gerar mudanças pequenas, revisáveis e testadas. Sem limites claros, ele tende a criar componentes demais, props demais e pouca evidência de qualidade.
Este guia cobre React + TypeScript na prática: limites de componentes, props, state, custom hooks, formulários, data fetching, Testing Library, acessibilidade, performance e prompt de revisão. Use as referências oficiais: React, React Testing Library, MDN ARIA e Claude Code. Para continuar no ClaudeCodeLab, leia TypeScript tips, estratégias de teste, acessibilidade e performance.
Contrato antes do código
Props são entradas passadas do componente pai para o filho. State é o que a interface lembra. Custom hook é uma função reutilizável para lógica com estado e efeitos. Efeitos incluem chamadas API, timers e localStorage.
| Informação | Exemplo | Benefício |
|---|---|---|
| Responsabilidade | listar, filtrar, ativar usuários | evita componente gigante |
| Local do state | pai, URL, hook, cache de servidor | evita useState espalhado |
| Dados | tipo User, resposta API, empty state | deixa props e testes claros |
| Verificação | npm test, npm run build, teclado | cria evidência para revisão |
Casos de uso reais
Primeiro: listas internas de admin, como usuários, pedidos, faturas, tickets e permissões. Claude Code pode separar filtros, tabela, ações de linha, empty state e erro sem alterar a API.
Segundo: formulários de perfil, contato, checkout ou inscrição em treinamento. Peça para preservar labels, validação, estado de envio e retry. Para formulários maiores, veja React Hook Form com Claude Code.
Terceiro: telas de dados do servidor, como busca, notificações e dashboards. Server state não deve se misturar com state temporário de UI. Para TanStack Query, use TanStack Query; para state pequeno no cliente, veja Zustand.
Quarto: revisão de diff. Peça para Claude Code encontrar fronteiras ruins, Effects desnecessários, falta de acessibilidade, testes frágeis e renders evitáveis.
Diagrama de componentes
UserAdminPage
-> UserFilters: busca e filtro de papel
-> UserTable: tabela e ações
-> UserStatusBadge: exibição de status
-> UserEditDialog: formulário
-> useUsers: fetch, refresh, erro
Componente React tipado
import type { FormEvent } from "react";
export type UserRole = "admin" | "editor" | "viewer";
export type User = {
id: string;
name: string;
email: string;
role: UserRole;
active: boolean;
};
type UserTableProps = {
users: User[];
selectedRole: "all" | UserRole;
onRoleChange: (role: "all" | UserRole) => void;
onToggleActive: (id: string) => void;
};
export function UserTable({ users, selectedRole, onRoleChange, onToggleActive }: UserTableProps) {
const filteredUsers = selectedRole === "all" ? users : users.filter((user) => user.role === selectedRole);
function handleRoleSubmit(event: FormEvent<HTMLFormElement>) {
event.preventDefault();
const formData = new FormData(event.currentTarget);
onRoleChange(formData.get("role") as "all" | UserRole);
}
return (
<section aria-labelledby="user-table-title">
<h2 id="user-table-title">Team members</h2>
<form onSubmit={handleRoleSubmit} style={{ marginBottom: 12 }}>
<label htmlFor="role">Filter by role </label>
<select id="role" name="role" defaultValue={selectedRole}>
<option value="all">All</option>
<option value="admin">Admin</option>
<option value="editor">Editor</option>
<option value="viewer">Viewer</option>
</select>
<button type="submit">Apply</button>
</form>
{filteredUsers.length === 0 ? (
<p role="status">No users match this filter.</p>
) : (
<table>
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Email</th>
<th scope="col">Role</th>
<th scope="col">Status</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
{filteredUsers.map((user) => (
<tr key={user.id}>
<td>{user.name}</td>
<td>{user.email}</td>
<td>{user.role}</td>
<td>{user.active ? "Active" : "Paused"}</td>
<td>
<button type="button" onClick={() => onToggleActive(user.id)}>
{user.active ? "Pause" : "Activate"}
</button>
</td>
</tr>
))}
</tbody>
</table>
)}
</section>
);
}
Hook e teste
import { useEffect, useState } from "react";
import type { User } from "./UserTable";
type UsersState =
| { status: "loading"; users: User[]; error: null }
| { status: "success"; users: User[]; error: null }
| { status: "error"; users: User[]; error: string };
export function useUsers(endpoint: string) {
const [state, setState] = useState<UsersState>({ status: "loading", users: [], error: null });
useEffect(() => {
const controller = new AbortController();
async function loadUsers() {
setState({ status: "loading", users: [], error: null });
try {
const response = await fetch(endpoint, { signal: controller.signal });
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const users = (await response.json()) as User[];
setState({ status: "success", users, error: null });
} catch (error) {
if (error instanceof DOMException && error.name === "AbortError") return;
setState({ status: "error", users: [], error: error instanceof Error ? error.message : "Unknown error" });
}
}
void loadUsers();
return () => controller.abort();
}, [endpoint]);
return state;
}
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { describe, expect, it, vi } from "vitest";
import { UserTable, type User } from "./UserTable";
const users: User[] = [
{ id: "1", name: "Masa", email: "masa@example.com", role: "admin", active: true },
{ id: "2", name: "Aiko", email: "aiko@example.com", role: "viewer", active: false },
];
describe("UserTable", () => {
it("filters users and toggles active status", async () => {
const user = userEvent.setup();
const onRoleChange = vi.fn();
const onToggleActive = vi.fn();
render(<UserTable users={users} selectedRole="all" onRoleChange={onRoleChange} onToggleActive={onToggleActive} />);
await user.selectOptions(screen.getByLabelText(/filter by role/i), "viewer");
await user.click(screen.getByRole("button", { name: /apply/i }));
await user.click(screen.getByRole("button", { name: /activate/i }));
expect(onRoleChange).toHaveBeenCalledWith("viewer");
expect(onToggleActive).toHaveBeenCalledWith("2");
});
});
Prompt de revisão
Revise este diff React + TypeScript.
Verifique limites de componentes, props em excesso, useEffect desnecessário, mistura de UI state e server state, labels e erros de formulário, cobertura com Testing Library e risco de re-render em listas grandes.
Não adicione bibliotecas. Termine com npm test e npm run build.
Armadilhas comuns
As falhas mais comuns são componentes gerados demais, useEffect para valores derivados, inputs sem label, botões de ícone sem nome acessível, erro indicado só por cor e performance sem medição. Peça a menor abstração útil e testes do ponto de vista do usuário.
CTA e resultado
Em times, registre as regras em CLAUDE.md: fronteiras, comandos de teste, acessibilidade e limites contra abstração exagerada. A consultoria e treinamento Claude Code da ClaudeCodeLab ajuda a aplicar isso em um repositório React real, com revisão UI, Testing Library, performance e CTAs de consulta ou venda.
Resultado prático: em uma UI administrativa de site de conteúdo, Masa reduziu retrabalho ao informar limites, dono do state e expectativas de teste antes da geração. O padrão confiável foi gerar diffs pequenos e verificáveis.
PDF grátis: cheatsheet do Claude Code
Informe seu e-mail e baixe uma página com comandos, hábitos de revisão e workflows seguros.
Cuidamos dos seus dados e não enviamos spam.
Sobre o autor
Masa
Engenheiro focado em workflows práticos com Claude Code.
Artigos relacionados
Workflow Obsidian para CLAUDE.md com Claude Code
Transforme notas de trabalho do Obsidian em notas operacionais CLAUDE.md para preservar contexto.
Claude Code Revenue CTA Routing: artigos para PDF, Gumroad e consultoria
Um fluxo com Claude Code para levar leitores ao PDF grátis, Gumroad ou consultoria conforme intenção.
Regras de handoff para equipes com Claude Code: evidências, permissões, rollback e receita
Formato prático para entregar trabalho do Claude Code com prova, permissões, rollback, PDF grátis, Gumroad e consultoria.