Use Cases (Aktualisiert: 2.6.2026)

React-Entwicklung mit Claude Code: Komponenten, Hooks, Tests und Review

Claude Code für sichere React-Entwicklung: typisierte Komponenten, Hooks, Tests, Accessibility und Review.

React-Entwicklung mit Claude Code: Komponenten, Hooks, Tests und Review

Claude Code kann React-Entwicklung stark beschleunigen, aber Produktionsteams brauchen mehr als schnelle Generierung. Sie brauchen kleine Änderungen, klare Grenzen, Tests und nachvollziehbare Reviews. Ohne präzise Vorgaben entstehen oft zu viele Komponenten, zu viele props und zu wenig Sicherheit.

Dieser Leitfaden zeigt einen praktischen Workflow für React + TypeScript: Komponenten-Grenzen, props, state, custom hooks, Formulare, Data Fetching, Testing Library, Accessibility, Performance und Review-Prompts. Nutze die offiziellen Quellen: React Docs, React Testing Library, MDN ARIA und Claude Code Docs. Passende ClaudeCodeLab-Artikel sind TypeScript-Tipps, Testing-Strategien, Accessibility und Performance-Optimierung.

Erst Vertrag, dann Code

Props sind Eingaben vom Parent an ein Child. State ist das, was die Oberfläche speichert. Ein custom hook ist eine wiederverwendbare Funktion für zustandsbehaftete Logik. Effekte sind API-Aufrufe, Timer oder Zugriffe auf Storage.

InformationBeispielNutzen
UI-AufgabeNutzerliste, Rollenfilter, Aktivierenverhindert Riesenkomponenten
State-OrtParent, URL, hook, Server-Cacheverhindert verstreute useState
DatenformUser, API Response, Empty Statemacht props und Tests konkret
Prüfungnpm test, npm run build, Tastaturliefert Review-Nachweise

Reale Use Cases

Erster Use Case: interne Admin-Listen für Nutzer, Rechnungen, Tickets oder Rollen. Claude Code kann Filter, Tabelle, Zeilenaktionen, Empty State und Fehlerzustand trennen, ohne API-Typen zu verändern.

Zweiter Use Case: Formulare für Profil, Kontakt, Checkout oder Trainingsanmeldung. Labels, Validierung, Submit-Status und Retry-Verhalten müssen erhalten bleiben. Für komplexere Formulare lies React Hook Form mit Claude Code.

Dritter Use Case: Seiten mit Serverdaten wie Suche, Benachrichtigungen oder Dashboards. Server State sollte nicht mit temporärem UI State vermischt werden. Für TanStack Query siehe TanStack Query, für kleinen Client State Zustand.

Vierter Use Case: Code Review. Lass Claude Code den Diff prüfen: unklare Grenzen, unnötige Effects, fehlende Labels, schwache Tests und vermeidbare Re-Renders.

Komponenten-Diagramm

UserAdminPage
  -> UserFilters: Suche und Rollenfilter
  -> UserTable: Tabelle und Aktionen
  -> UserStatusBadge: nur Statusanzeige
  -> UserEditDialog: Formular
  -> useUsers: fetch, refresh, error

Wenn sich die props eines Components nicht in einem Satz erklären lassen, macht er wahrscheinlich zu viel. Wenn er nur einmal vorkommt und kein eigenes Verhalten hat, ist die Extraktion vielleicht zu früh.

Typisierte React-Komponente

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 und Test

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");
  });
});

Review-Prompt

Reviewe diesen React + TypeScript Diff.
Prüfe Komponenten-Grenzen, zu viele props, unnötige useEffect-Nutzung, vermischten UI State und Server State, Formularlabels, Fehlermeldungen, Testing-Library-Abdeckung und Re-Render-Risiken.
Füge keine neuen Libraries hinzu. Beende mit npm test und npm run build.

Häufige Fehler

Typische Probleme sind übergenerierte Komponenten, abgeleitete Werte in useEffect, Inputs ohne Label, Icon-Buttons ohne zugänglichen Namen, Fehler nur über Farbe und Performance-Optimierung ohne Messung. Gib Claude Code die Regel: kleinste sinnvolle Abstraktion, Nutzerperspektive im Test, Accessibility nicht nachträglich.

CTA und Ergebnis

Für Teams gehören diese Regeln in CLAUDE.md: Komponenten-Grenzen, Testbefehle, Accessibility und verbotene Überabstraktion. ClaudeCodeLab bietet Claude Code Training und Beratung für reale React-Repositories, inklusive UI-Review, Testing Library, Performance-Nachweisen und conversion-orientierten Formularen oder CTAs.

Praktisches Ergebnis: Bei einer Admin-UI für eine Content-Seite reduzierte Masa Nacharbeit, weil Claude Code zuerst Grenzen, State-Verantwortung und Testerwartungen bekam. Der stabile Weg ist ein kleiner, verifizierbarer Diff, nicht maximale Generierung.

#Claude Code #React #frontend #components #Hooks
Kostenlos

Kostenloses PDF: Claude-Code-Cheatsheet

E-Mail eintragen und eine Seite mit Befehlen, Review-Gewohnheiten und sicheren Workflows herunterladen.

Wir schützen Ihre Daten und senden keinen Spam.

Masa

Über den Autor

Masa

Engineer für praktische Claude-Code-Workflows und Team-Einführung.