Communitygithub.com

react-patterns

React 18/19-Muster, einschließlich Hooks-Disziplin, Server/Client-Komponenten-Grenzen, Suspense + Error Boundaries, Formular-Aktionen, Datenabruf, Entscheidungsbäume für State-Management und Barrierefreiheit. Verwenden Sie diese, wenn Sie React-Komponenten schreiben oder überprüfen.

Was ist react-patterns?

Die Skill 'react-patterns' ist ein umfassendes Nachschlagewerk für moderne React-Entwicklung mit Versionen 18 und 19. Sie definiert klare Prinzipien (Render als reine Funktion von Props und State, Side Effects außerhalb des Renders, Komposition über Vererbung) und bietet eine Hooks-Disziplin mit Empfehlungen zur Memoisierung und Extraktion eigener Hooks. Ein Entscheidungsbaum hilft, den richtigen Ort für State (useState, Lifting, Context, externer Store) zu wählen. Die Skill behandelt Server/Client-Komponenten (RSC), Suspense + Error Boundaries, die neuen Formular-Aktionen aus React 19, kontrollierte Inputs und komplexe Formulare. Sie bietet eine Entscheidungsmatrix für Datenabfrage-Tools (RSC fetch, TanStack Query, SWR, SSE) und Rezepte für Komposition (Slots, Compound Components, Render Props). Performance-Tipps (React.memo, Renderkaskaden vermeiden, Listen virtualisieren) und Barrierefreiheit (semantisches HTML, Tastaturzugänglichkeit) sind ebenfalls enthalten. Die Skill ist Router-unabhängig und verweist auf verwandte Skills und Regeln.

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

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

React Patterns

Idiomatische React 18/19-Muster für den Aufbau robuster, barrierefreier und performanter Komponentenbäume.

Wann aktivieren

  • Schreiben oder Ändern von React-Funktionskomponenten, benutzerdefinierten Hooks oder Komponentenbäumen
  • Überprüfen von JSX/TSX-Dateien
  • Entwerfen von State-Shape oder Komponentenkomposition
  • Migrieren von Klassenkomponenten oder älterem forwardRef/useEffect-lastigem Code
  • Auswahl zwischen lokalem State, gehobenem State, Context und externen Stores
  • Arbeiten mit Server Components / Client Components (Next.js App Router, RSC)
  • Implementieren von Formularen mit React 19-Aktionen oder kontrollierten Eingaben
  • Anbinden von Datenabruf mit TanStack Query / SWR / RSC

Kernprinzipien

1. Render ist eine reine Funktion von Props und State

// Gut: während des Renders ableiten
function Cart({ items }: { items: CartItem[] }) {
  const total = items.reduce((sum, i) => sum + i.price * i.qty, 0);
  return <span>{formatMoney(total)}</span>;
}

// Schlecht: abgeleiteter State separat gespeichert
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>;
}

Abgeleiteter State in useEffect fügt einen Render-Zyklus hinzu, kann desynchronisieren und verschleiert den Datenfluss.

2. Side Effects außerhalb des Renders

Effekte, Mutationen, Netzwerkaufrufe und Subscriptions leben in Event-Handlern oder useEffect – niemals im Render-Body.

3. Komposition vor Vererbung

React hat kein Vererbungsmodell für Komponenten. Komponieren Sie mit children, Render Props oder Komponenten-Props.

Hooks-Disziplin

Siehe rules/react/hooks.md für das vollständige Regelset. Highlights:

  • Nur auf oberster Ebene, niemals konditional
  • Jede Subscription, jedes Intervall, jeden Listener aufräumen
  • Funktionale Updater (setX(prev => prev + 1)) wenn neuer State vom alten abhängt
  • Standardposition: nicht memoizen – useMemo/useCallback nur hinzufügen, wenn ein Profiler oder eine Abhängigkeitskette es als wichtig erweist
  • Einen benutzerdefinierten Hook nur extrahieren, wenn dieselbe Hook-Sequenz in 2+ Komponenten auftritt

Entscheidungsbaum für State-Position

Wird von einer Komponente verwendet?
  -> useState darin

Wird von einer Eltern- und einigen Nachkommen verwendet?
  -> auf den nächsten gemeinsamen Vorfahren heben

Wird von entfernten Zweigen verwendet UND hat niedrige Lesehäufigkeit (Theme, Auth, Locale)?
  -> React Context

High-Frequency-Updates, die über den Baum geteilt werden?
  -> externer Store (Zustand, Jotai, Redux Toolkit)

Wird von einem Server abgeleitet?
  -> Server-State-Bibliothek (TanStack Query, SWR, RSC fetch)

Die meisten Seiten benötigen weder Context noch einen globalen Store. Widerstehen Sie der Abstraktion, bis das duplizierte Heben schmerzhaft wird.

Server / Client Components (RSC)

// Server Component - Standard, asynchron, versendet niemals JS für sich selbst
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 - mit "use client" aktivieren
"use client";
export function AddToCartButton({ productId }: { productId: string }) {
  const [pending, startTransition] = useTransition();
  return (
    <button
      disabled={pending}
      onClick={() => startTransition(() => addToCart(productId))}
    >
      {pending ? "Adding..." : "Add to cart"}
    </button>
  );
}

Grenzen:

  • Server -> Client: serialisierbare Props oder children übergeben
  • Client -> Server: Server Actions über <form action={...}> oder imperativ aus Event-Handlern aufrufen
  • Niemals eine Server Component aus einer Client Component-Datei importieren – stattdessen via children komponieren

Suspense + Error Boundaries

<ErrorBoundary fallback={<ErrorView />}>
  <Suspense fallback={<UserSkeleton />}>
    <UserDetail id={id} />
  </Suspense>
</ErrorBoundary>
  • Suspense-Grenzen nahe an den Daten platzieren, nicht auf Router-Ebene – Inhalt progressiv anzeigen
  • Error Boundary bleibt eine Klassen-API; react-error-boundary für einen hook-freundlichen Wrapper verwenden
  • Eine Boundary fängt Fehler, die während des Renders, des Lifecycles und der Konstruktoren ihrer Kinder geworfen werden – NICHT in Event-Handlern oder asynchronem Code

Formulare

React 19-Formular-Aktionen (bevorzugt für neuen Code)

"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: "Invalid input" };
  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}>Save</button>
      {state.error && <p role="alert">{state.error}</p>}
    </form>
  );
}

Kontrollierte Eingaben

Verwenden Sie kontrollierte Eingaben, wenn der Wert andere UI-Elemente steuert, bei jedem Tastendruck formatiert oder eine Echtzeit-Validierung implementiert.

Komplexe Formulare

Für mehrstufige Formulare, dynamische Feld-Arrays oder validierung über Felder hinweg: Verwenden Sie eine Bibliothek (React Hook Form, TanStack Form). Eigenes State-Management für Formulare mit mehr als trivialer Komplexität ist eine Wartungsfalle.

Entscheidungsmatrix für Datenabruf

BedarfWerkzeug
Pro-Request-Daten in Next.js App RouterRSC await fetch()
Client-seitiger Cache + Mutationen + InvalidierungTanStack Query
Leichter Client-Cache + RevalidierungSWR
Echtzeit-SubscriptionsServer-Sent Events, WebSockets oder die Subscription-API der Bibliothek
Einmalig "Feuer und Vergiss"fetch() in einem Event-Handler

Vermeiden Sie useEffect + fetch für Anwendungsdaten – Race Conditions, kein Cache, kein Retry, keine Suspense-Integration.

Kompositionsrezepte

Slot via children

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

Benannte Slots

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

Compound Components (geteilter State via Context)

<Tabs defaultValue="profile">
  <Tabs.List>
    <Tabs.Trigger value="profile">Profile</Tabs.Trigger>
    <Tabs.Trigger value="settings">Settings</Tabs.Trigger>
  </Tabs.List>
  <Tabs.Panel value="profile"><Profile /></Tabs.Panel>
  <Tabs.Panel value="settings"><Settings /></Tabs.Panel>
</Tabs>

Render Prop / Function-as-Child

Nützlich, wenn die Elternkomponente Parameter an die gerenderte Ausgabe übergeben muss:

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

Moderne Alternative: ein Hook (useData(id)), der die gleiche Form zurückgibt – normalerweise sauberer.

Performance

Wann React.memo wirklich hilft

Wickeln Sie eine Komponente nur dann in React.memo, wenn:

  1. Sie häufig neu rendert
  2. Ihre Props zwischen den Rendern meist gleich sind
  3. Ihr Render messbar teuer ist

React.memo fügt bei jedem Render einen Gleichheitscheck hinzu. Wenn sich Props bei den meisten Rendern unterscheiden, ist der Check reiner Overhead.

Renderkaskaden vermeiden

  • State eher nach unten als nach oben heben
  • Context aufteilen: ein Context pro Belang, sodass eine Änderung von themeContext keine Auth-Konsumenten neu rendert
  • useSyncExternalStore für externe State-Bibliotheken verwenden – erforderlich für sicheres Concurrent Rendering

Listen

  • Stabile key-Props bereitstellen (Datenbank-ID, nicht Array-Index)
  • Lange Listen mit @tanstack/react-virtual oder react-window virtualisieren, sobald die sichtbare Anzahl ~50 mit nicht-trivialen Zeilen überschreitet

Barrierefreiheit zuerst

  • Immer semantisches HTML rendern (<button>, <a>, <nav>, <main>), bevor role-Attribute verwendet werden
  • Jedes interaktive Element muss per Tastatur erreichbar sein
  • Formulareingaben benötigen Labels – <label htmlFor> oder aria-label, wenn visuell durch ein Icon beschriftet
  • Fokus bei Routenwechseln und Modal-Öffnen/-Schließen verwalten
  • axe in Komponententests ausführen (siehe skills/react-testing)
  • Querverweis: skills/accessibility/SKILL.md behandelt WCAG-Kriterien und Pattern-Bibliotheken

Routing

Diese Skill ist Router-unabhängig. Die obigen Muster funktionieren mit React Router, TanStack Router, Next.js App Router, Remix Router. Router-spezifische Muster (Loader, Actions, verschachtelte Layouts) folgen der Dokumentation des jeweiligen Routers – das sind Framework-Belange, die auf dem React-Kern aufbauen.

Nicht abgedeckt (Verweissektionen)

  • Next.js-Spezifika: App Router-Datenladen, Route Handler, Middleware, Parallel Routes – separates Thema, Next.js-Dokumentation verwenden
  • React Native: Plattformspezifische Muster unterscheiden sich genug, um eine separate react-native-patterns-Skill zu rechtfertigen (noch nicht vorhanden)
  • Remix: Loader/Action-Konventionen überschneiden sich mit RSC, aber der Remix-Dokumentation folgen

Verwandtes

  • Regeln: rules/react/ – Codestyle, Hooks, Muster, Sicherheit, Tests
  • Skills: react-performance für das von Vercel abgeleitete Performance-Regelset, frontend-patterns für framework-übergreifende UI-Belange, accessibility, angular-developer für Framework-Vergleich
  • Agents: react-reviewer für Code-Review, react-build-resolver für Build/Bundler-Fehler
  • Befehle: /react-review, /react-build, /react-test

Beispiele

Benutzerdefinierter Hook für debounce-Suche

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 ?? []} />
    </>
  );
}

Optimistische UI mit React 19 useOptimistic

"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">Send</button>
      </form>
    </>
  );
}

Context aufteilen, um Renderkaskaden zu vermeiden

// Zwei Contexts: einer ändert sich selten, einer häufig
const ThemeContext = createContext<Theme>("light");
const NotificationsContext = createContext<Notification[]>([]);

// Eine Komponente, die nur ThemeContext konsumiert, rendert NICHT neu, wenn sich Benachrichtigungen ändern

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.

Verwandte Skills