Communitygithub.com

react-patterns

Padrões React 18/19 incluindo disciplina de hooks, limites entre componentes servidor/cliente, Suspense + Error Boundaries, actions de formulário, busca de dados, árvores de decisão para gerenciamento de estado e composição com acessibilidade em primeiro lugar. Use ao escrever ou revisar componentes React.

O que é react-patterns?

Este skill fornece um conjunto abrangente de padrões idiomáticos para React 18 e 19, com foco na construção de componentes robustos, acessíveis e de alto desempenho. Ele é ativado ao escrever ou modificar componentes de função, hooks personalizados, ou ao revisar arquivos JSX/TSX. O skill abrange desde decisões sobre onde colocar o estado (árvore de decisão de localização de estado) até padrões avançados como Server Components (RSC), Client Components, Suspense e Error Boundaries, e actions de formulário do React 19. Ele também inclui práticas recomendadas de composição, como slots via children, componentes compostos e render props, além de orientações sobre desempenho (quando usar React.memo, virtuallização de listas) e acessibilidade (HTML semântico, foco, labels). O conteúdo é agnóstico a roteadores e se concentra no core do React, complementando outros skills como react-performance e accessibility.

Funciona com✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/ECC/tree/main/skills/react-patterns

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

Padrões React

Padrões idiomáticos React 18/19 para construir árvores de componentes robustas, acessíveis e de alto desempenho.

Quando Ativar

  • Escrevendo ou modificando componentes de função React, hooks personalizados ou árvores de componentes
  • Revisando arquivos JSX/TSX
  • Projetando forma de estado ou composição de componentes
  • Migrando componentes de classe ou código antigo com forwardRef/useEffect pesado
  • Escolhendo entre estado local, estado elevado, contexto e stores externas
  • Trabalhando com Server Components / Client Components (Next.js App Router, RSC)
  • Implementando formulários com actions do React 19 ou inputs controlados
  • Integrando busca de dados com TanStack Query / SWR / RSC

Princípios Centrais

1. Renderização é uma Função Pura de Props e Estado

// Bom: deriva durante a renderização
function Cart({ items }: { items: CartItem[] }) {
  const total = items.reduce((sum, i) => sum + i.price * i.qty, 0);
  return <span>{formatMoney(total)}</span>;
}

// Ruim: estado derivado armazenado separadamente
function Cart({ items }: { items: CartItem[] }) {
  const [total, setTotal] = useState(0);
  useEffect(() => {
    setTotal(items.reduce((sum, i) => sum + i.price * i.qty, 0));
  }, [items]);
  return <span>{formatMoney(total)}</span>;
}

Estado derivado em useEffect adiciona um ciclo de renderização, pode dessincronizar e obscurece o fluxo de dados.

2. Efeitos Colaterais Fora da Renderização

Efeitos, mutações, chamadas de rede e inscrições vivem em manipuladores de eventos ou useEffect — nunca no corpo da renderização.

3. Composição Sobre Herança

React não tem modelo de herança para componentes. Componha com children, render props ou props de componente.

Disciplina de Hooks

Veja rules/react/hooks.md para o conjunto completo de regras. Destaques:

  • Apenas no nível superior, nunca condicionais
  • Limpeza de toda inscrição, intervalo, listener
  • Atualizador funcional (setX(prev => prev + 1)) quando novo estado depende do anterior
  • Posição padrão: não memorizar — adicione useMemo/useCallback apenas quando um profiler ou uma cadeia de dependências provar que é necessário
  • Extraia um hook personalizado apenas quando a mesma sequência de hooks aparecer em 2+ componentes

Árvore de Decisão de Localização de Estado

Usado por um único componente?
  -> useState dentro dele

Usado pelo pai + alguns descendentes?
  -> elevar ao ancestral comum mais próximo

Usado em ramos distantes E leituras de baixa frequência (tema, autenticação, localidade)?
  -> React Context

Atualizações de alta frequência compartilhadas pela árvore?
  -> store externa (Zustand, Jotai, Redux Toolkit)

Derivado de um servidor?
  -> biblioteca de estado do servidor (TanStack Query, SWR, fetch RSC)

A maioria das páginas não precisa de contexto ou store global. Resista à abstração até que a elevação duplicada se torne dolorosa.

Server / Client Components (RSC)

// Server Component - padrão, assíncrono, nunca envia JS para si mesmo
export default async function ProductPage({ params }: { params: { id: string } }) {
  const product = await db.product.findUnique({ where: { id: params.id } });
  if (!product) notFound();
  return <ProductView product={product} />;
}

// Client Component - opte com "use client"
"use client";
export function AddToCartButton({ productId }: { productId: string }) {
  const [pending, startTransition] = useTransition();
  return (
    <button
      disabled={pending}
      onClick={() => startTransition(() => addToCart(productId))}
    >
      {pending ? "Adicionando..." : "Adicionar ao carrinho"}
    </button>
  );
}

Limites:

  • Server -> Client: passe props serializáveis ou children
  • Client -> Server: invoque Server Actions via <form action={...}> ou imperativamente a partir de manipuladores de eventos
  • Nunca import um Server Component de um arquivo Client Component — componha-os via children

Suspense + Error Boundaries

<ErrorBoundary fallback={<ErrorView />}>
  <Suspense fallback={<UserSkeleton />}>
    <UserDetail id={id} />
  </Suspense>
</ErrorBoundary>
  • Coloque os limites Suspense próximos aos dados, não na raiz da rota — revele conteúdo progressivamente
  • Error Boundary continua sendo uma API de classe; use react-error-boundary para um wrapper amigável a hooks
  • Um boundary captura erros lançados durante a renderização, ciclo de vida e construtores de seus filhos — NÃO em manipuladores de eventos ou código assíncrono

Formulários

Actions de formulário do React 19 (preferido para código novo)

"use client";
import { useActionState } from "react";

const initial = { error: null as string | null };

async function updateUserAction(_prev: typeof initial, formData: FormData) {
  "use server";
  const parsed = UserSchema.safeParse(Object.fromEntries(formData));
  if (!parsed.success) return { error: "Entrada inválida" };
  await db.user.update({ where: { id: parsed.data.id }, data: parsed.data });
  return { error: null };
}

export function UserForm() {
  const [state, formAction, pending] = useActionState(updateUserAction, initial);
  return (
    <form action={formAction}>
      <input name="name" required />
      <button type="submit" disabled={pending}>Salvar</button>
      {state.error && <p role="alert">{state.error}</p>}
    </form>
  );
}

Inputs controlados

Use controlado quando o valor direciona outra UI, formata a cada tecla, ou implementa validação em tempo real.

Formulários complexos

Para formulários multi-etapas, arrays de campos dinâmicos ou validação entre campos: use uma biblioteca (React Hook Form, TanStack Form). Gerenciar estado manualmente para formulários além da complexidade trivial é uma armadilha de manutenção.

Matriz de Decisão de Busca de Dados

NecessidadeFerramenta
Dados por requisição no Next.js App RouterRSC await fetch()
Cache do lado do cliente + mutações + invalidaçãoTanStack Query
Cache cliente leve + revalidaçãoSWR
Inscrições em tempo realServer-Sent Events, WebSockets, ou a API de inscrição da lib
Único disparo e esquecefetch() em um manipulador de evento

Evite useEffect + fetch para dados de aplicação — condições de corrida, sem cache, sem repetição, sem integração com Suspense.

Receitas de Composição

Slot via children

<Layout>
  <Header />
  <Main>{content}</Main>
</Layout>

Slots nomeados

<Page header={<Nav />} sidebar={<Filters />}>
  <Results />
</Page>

Componentes compostos (estado compartilhado via Context)

<Tabs defaultValue="profile">
  <Tabs.List>
    <Tabs.Trigger value="profile">Perfil</Tabs.Trigger>
    <Tabs.Trigger value="settings">Configurações</Tabs.Trigger>
  </Tabs.List>
  <Tabs.Panel value="profile"><Profile /></Tabs.Panel>
  <Tabs.Panel value="settings"><Settings /></Tabs.Panel>
</Tabs>

Render prop / função como filho

Útil quando o pai precisa passar parâmetros para a saída renderizada:

<DataLoader id={id}>
  {({ data, isLoading }) => isLoading ? <Spinner /> : <UserCard user={data} />}
</DataLoader>

Alternativa moderna: um hook (useData(id)) retornando a mesma forma — geralmente mais limpo.

Desempenho

Quando React.memo Realmente Ajuda

Envolva um componente em React.memo apenas quando:

  1. Ele re-renderiza frequentemente
  2. Suas props são geralmente as mesmas entre renderizações
  3. Sua renderização é mensuravelmente cara

React.memo adiciona uma verificação de igualdade em cada renderização. Se as props diferirem na maioria das renderizações, a verificação é pura sobrecarga.

Evitando Cascatas de Renderização

  • Eleve o estado para baixo em vez de para cima quando possível
  • Divida contexto: um contexto por preocupação, para que uma mudança em themeContext não re-renderize consumidores de autenticação
  • Use useSyncExternalStore para bibliotecas de estado externo — necessário para renderização concorrente segura

Listas

  • Forneça props key estáveis (id do banco de dados, não índice do array)
  • Virtualize listas longas com @tanstack/react-virtual ou react-window quando a contagem de itens visíveis exceder ~50 com linhas não triviais

Composição com Acessibilidade em Primeiro Lugar

  • Sempre renderize HTML semântico (<button>, <a>, <nav>, <main>) antes de recorrer a atributos role
  • Todo elemento interativo deve ser acessível por teclado
  • Inputs de formulário precisam de labels — <label htmlFor> ou aria-label se rotulado visualmente por um ícone
  • Gerencie o foco em mudanças de rota e abertura/fechamento de modal
  • Execute axe em testes de componente (veja skills/react-testing)
  • Link cruzado: skills/accessibility/SKILL.md cobre critérios WCAG e bibliotecas de padrões

Roteamento

Este skill é agnóstico a roteadores. Os padrões acima funcionam com React Router, TanStack Router, Next.js App Router, Remix Router. Padrões específicos de roteador (loaders, actions, layouts aninhados) seguem a documentação do roteador — são preocupações de framework sobrepostas ao núcleo do React.

Fora do Escopo (Seções de Referência)

  • Especificidades do Next.js: Carregamento de dados do App Router, Route Handlers, Middleware, Parallel Routes — preocupação separada, use a documentação do Next.js
  • React Native: Padrões específicos de plataforma diferem o suficiente para justificar um skill separado react-native-patterns (ainda não presente)
  • Remix: Convenções de loader/action se sobrepõem ao RSC, mas sigam a documentação do Remix

Relacionados

  • Regras: rules/react/ — estilo de código, hooks, padrões, segurança, testes
  • Skills: react-performance para o conjunto de regras de desempenho derivado da Vercel, frontend-patterns para preocupações de UI entre frameworks, accessibility, angular-developer para comparação de frameworks
  • Agentes: react-reviewer para revisão de código, react-build-resolver para erros de build/bundler
  • Comandos: /react-review, /react-build, /react-test

Exemplos

Hook personalizado para busca com debounce

function useDebounce<T>(value: T, delay = 300): T {
  const [debounced, setDebounced] = useState(value);
  useEffect(() => {
    const id = setTimeout(() => setDebounced(value), delay);
    return () => clearTimeout(id);
  }, [value, delay]);
  return debounced;
}

function SearchBox() {
  const [query, setQuery] = useState("");
  const debounced = useDebounce(query, 300);
  const { data } = useQuery({
    queryKey: ["search", debounced],
    queryFn: () => searchApi(debounced),
    enabled: debounced.length > 0,
  });
  return (
    <>
      <input value={query} onChange={(e) => setQuery(e.target.value)} />
      <Results items={data ?? []} />
    </>
  );
}

UI Otimista com useOptimistic do React 19

"use client";
import { useOptimistic } from "react";

export function MessageList({ messages }: { messages: Message[] }) {
  const [optimistic, addOptimistic] = useOptimistic(
    messages,
    (state, newMessage: Message) => [...state, newMessage],
  );

  async function send(formData: FormData) {
    const text = String(formData.get("text"));
    addOptimistic({ id: "pending", text, sender: "me" });
    await saveMessage(text);
  }

  return (
    <>
      <ul>{optimistic.map((m) => <li key={m.id}>{m.text}</li>)}</ul>
      <form action={send}>
        <input name="text" />
        <button type="submit">Enviar</button>
      </form>
    </>
  );
}

Dividindo contexto para evitar cascatas de renderização

// Dois contextos: um raramente muda, outro frequentemente
const ThemeContext = createContext<Theme>("light");
const NotificationsContext = createContext<Notification[]>([]);

// Um componente que consome apenas ThemeContext NÃO re-renderiza quando notificações mudam

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

accessibility

Design, implement, and audit inclusive digital products using WCAG 2.2 Level AA. Use when building or auditing UI that must meet WCAG 2.2 Level AA, or when reviewing a change for keyboard, contrast, or screen-reader support.

affaan-m/content-engine

Create platform-native content systems for X, LinkedIn, TikTok, YouTube, newsletters, and repurposed multi-platform campaigns. Use when the user wants social posts, threads, scripts, content calendars, or one source asset adapted cleanly across platforms.

affaan-m/ECC

Multi-platform content distribution across X, LinkedIn, Threads, and Bluesky. Adapts content per platform using content-engine patterns. Never posts identical content cross-platform. Use when the user wants to distribute content across social platforms.

affaan-m/fal-ai-media

Unified media generation via fal.ai MCP — image, video, and audio. Covers text-to-image (Nano Banana), text/image-to-video (Seedance, Kling, Veo 3), text-to-speech (CSM-1B), and video-to-audio (ThinkSound). Use when the user wants to generate images, videos, or audio with AI.

affaan-m/manim-video

日本語翻訳:このファイルは manim-video 用の日本語翻訳が必要です

affaan-m/remotion-video-creation

Remotion のベストプラクティス - React で動画を作成する。3D、アニメーション、音声、字幕、チャート、トランジションなどをカバーするドメイン固有の29のルール。

affaan-m/video-editing

AI-assisted video editing workflows for cutting, structuring, and augmenting real footage. Covers the full pipeline from raw capture through FFmpeg, Remotion, ElevenLabs, fal.ai, and final polish in Descript or CapCut. Use when the user wants to edit video, cut footage, create vlogs, or build video content.

agent-architecture-audit

Full-stack diagnostic for agent and LLM applications. Audits the 12-layer agent stack for wrapper regression, memory pollution, tool discipline failures, hidden repair loops, and rendering corruption. Produces severity-ranked findings with code-first fixes. Essential for developers building agent applications, autonomous loops, or any LLM-powered feature. Use when an agent or LLM feature misbehaves and the failing layer is unknown, or before shipping an agent stack.

agent-eval

Head-to-head comparison of coding agents (Claude Code, Aider, Codex, etc.) on custom tasks with pass rate, cost, time, and consistency metrics. Use when choosing between coding agents, or when a change to an agent setup needs measured pass rate, cost, and time rather than an impression.

agent-harness-construction

Design and optimize AI agent action spaces, tool definitions, and observation formatting for higher completion rates. Use when defining or revising an agent

agentic-engineering

Operate as an agentic engineer using eval-first execution, decomposition, and cost-aware model routing. Use when planning or executing engineering work that agents will carry out end to end.

agentic-os

Build persistent multi-agent operating systems on Claude Code. Covers kernel architecture, specialist agents, slash commands, file-based memory, scheduled automation, and state management without external databases. Use when building a persistent multi-agent system on Claude Code with its own memory, commands, and scheduling.

agent-introspection-debugging

Structured self-debugging workflow for AI agent failures using capture, diagnosis, contained recovery, and introspection reports. Use when an agent run fails and you need a reproducible diagnosis instead of a retry.

agent-payment-x402

Add x402 payment execution to AI agents with per-task budgets, spending controls, and non-custodial wallets. Supports Base through agentwallet-sdk and X Layer through OKX Payments / OKX Agent Payments Protocol. Use when an agent must pay for something itself and needs per-task budgets, spending controls, and a non-custodial wallet.

agent-self-evaluation

Use after completing any non-trivial task. The agent self-rates its output on 5 axes — accuracy, completeness, clarity, actionability, conciseness — with concrete evidence per criterion. Produces a structured 1-5 scorecard with specific improvement suggestions.

agent-sort

Build an evidence-backed ECC install plan for a specific repo by sorting skills, commands, rules, hooks, and extras into DAILY vs LIBRARY buckets using parallel repo-aware review passes. Use when ECC should be trimmed to what a project actually needs instead of loading the full bundle.

ai-first-engineering

Engineering operating model for teams where AI agents generate a large share of implementation output. Use when setting team process, review gates, or ownership rules for a codebase largely written by agents.

ai-regression-testing

Regression testing strategies for AI-assisted development. Sandbox-mode API testing without database dependencies, automated bug-check workflows, and patterns to catch AI blind spots where the same model writes and reviews code. Use when adding regression coverage to AI-assisted code, or when the same model both wrote and reviewed a change.

android-clean-architecture

Clean Architecture patterns for Android and Kotlin Multiplatform projects — module structure, dependency rules, UseCases, Repositories, and data layer patterns. Use when structuring modules, layers, or data flow in an Android or KMP project.

angular-developer

Generates Angular code and provides architectural guidance. Trigger when creating projects, components, or services, or for best practices on reactivity (signals, linkedSignal, resource), forms, dependency injection, routing, SSR, accessibility (ARIA), animations, styling (component styles, Tailwind CSS), testing, or CLI tooling.

Habilidades Relacionadas