React 19 Hooks Cheatsheet: alle Hooks und wann nutzen
AI generated
</>
{ }
React · Hooks · React 19 · Cheatsheet
React 19 Hooks Cheatsheet
alle Hooks und wann genau nutzen

React 19 bringt neue Hooks und verfeinert bestehende – doch das größte Problem in der Praxis ist nicht Unkenntnis, sondern falsche Wahl: useEffect wo useRef reicht, useMemo wo kein Memoizing nötig ist. Dieses Cheatsheet gibt klare Entscheidungsregeln, wann welcher React Hook der richtige ist.

18 Min. Lesezeit useState · useEffect · useRef · useMemo · useCallback · useTransition · useActionState React 19 · JavaScript · TypeScript

1. Warum React Hooks das Komponentenmodell verändert haben

Vor der Einführung von React Hooks in Version 16.8 musste man für jeden Zustand und jeden Seiteneffekt auf Klassenkomponenten mit this.setState, Lifecycle-Methoden wie componentDidMount und shouldComponentUpdate zurückgreifen. Das Ergebnis waren verschachtelte Higher-Order Components und Render Props, die dieselbe Logik mehrfach über verschiedene Komponenten streuten und kaum testbar waren. React Hooks ermöglichen es, zustandsbehaftete Logik direkt in Funktionskomponenten zu kapseln und zwischen Komponenten in Custom Hooks wiederzuverwenden, ohne die Komponentenhierarchie zu verändern.

React 19 baut auf dieser Grundlage auf und bringt mit useActionState, useFormStatus und verbesserten Concurrency-Features neue React Hooks, die speziell auf Server Components und Server Actions ausgerichtet sind. Das Verständnis aller React Hooks und ihrer Einsatzbereiche ist damit wichtiger denn je: Die falsche Wahl – etwa useMemo für eine einfache Berechnung oder useEffect für eine synchrone Transformation – verschlechtert Lesbarkeit und Performance gleichzeitig. Dieses Cheatsheet gibt klare Entscheidungsregeln für jeden einzelnen Hook.

2. useState – lokaler Zustand einfach und sicher verwalten

useState ist der grundlegendste React Hook und der erste Griff, wenn eine Komponente auf Benutzereingaben oder interne Ereignisse reagieren soll. Er liefert ein Wert-Setter-Paar: const [value, setValue] = useState(initialValue). Jeder Aufruf von setValue löst einen Re-Render der Komponente aus, bei dem React den neuen Zustandswert liefert. Die Initialfunktion – useState(() => berechneAufwändig()) – wird nur beim ersten Render aufgerufen und verhindert teure Berechnungen bei jedem Re-Render. Der Unterschied zwischen setValue(newValue) und dem funktionalen Update setValue(prev => prev + 1) ist entscheidend: Letzteres liest den aktuellen Zustand zum Zeitpunkt der Ausführung, nicht den zum Zeitpunkt der Closure-Erstellung.

Wann useState der falsche React Hook ist: Wenn der Wert sich ändert, aber keinen Re-Render auslösen soll – dann ist useRef die richtige Wahl. Wenn der Zustand von vielen Komponenten auf verschiedenen Ebenen geteilt werden muss, sollte man useContext oder einen externen State-Manager in Betracht ziehen. Wenn die Zustandslogik komplex ist und mehrere Sub-Werte voneinander abhängen, ist useReducer oft lesbarer als mehrere useState-Aufrufe. Als Faustregel gilt: useState für einfache, unabhängige Werte, die direkt an das Rendering einer einzelnen Komponente gebunden sind.


import { useState, useReducer } from 'react';

// Simple counter — useState is the right choice here
function Counter() {
  const [count, setCount] = useState(0);

  // Functional update: reads current state, not stale closure value
  const increment = () => setCount(prev => prev + 1);
  const decrement = () => setCount(prev => prev - 1);

  return (
    <div>
      <button onClick={decrement}>-</button>
      <span>{count}</span>
      <button onClick={increment}>+</button>
    </div>
  );
}

// Complex form state — useReducer is cleaner than multiple useState calls
type FormState = { name: string; email: string; loading: boolean; error: string | null };
type FormAction = { type: 'SET_FIELD'; field: keyof FormState; value: string }
               | { type: 'SET_LOADING'; value: boolean }
               | { type: 'SET_ERROR'; value: string | null };

function formReducer(state: FormState, action: FormAction): FormState {
  switch (action.type) {
    case 'SET_FIELD': return { ...state, [action.field]: action.value };
    case 'SET_LOADING': return { ...state, loading: action.value };
    case 'SET_ERROR': return { ...state, error: action.value };
    default: return state;
  }
}

function ContactForm() {
  const [state, dispatch] = useReducer(formReducer, {
    name: '', email: '', loading: false, error: null,
  });

  return (
    <input value={state.name} onChange={e =>
      dispatch({ type: 'SET_FIELD', field: 'name', value: e.target.value })
    } />
  );
}

3. useEffect – Seiteneffekte richtig koordinieren

useEffect ist der am häufigsten missbrauchte React Hook. Er ist für Seiteneffekte gedacht – also Aktionen, die außerhalb des React-Render-Zyklus passieren: Datenabruf, manuelle DOM-Manipulation, Event-Listener registrieren, Timer setzen, externe Systeme abonnieren. Der Hook läuft nach jedem Render, es sei denn, ein Dependency Array schränkt die Ausführung ein. Das leere Array [] bedeutet: nur beim ersten Mount ausführen. Die Cleanup-Funktion im Rückgabewert wird vor dem nächsten Effekt-Aufruf und beim Unmount ausgeführt und ist unerlässlich für das Abmelden von Subscriptions und das Abbrechen laufender Requests.

Was in useEffect nicht gehört: synchrone Transformationen von Props oder State, die direkt in den Render-Output einfließen – diese gehören direkt in den Render-Body oder in useMemo. Ereignis-Handler, die nur auf direkte Benutzerinteraktionen reagieren, sollten nicht über useEffect koordiniert werden. In React 19 und mit dem React Compiler werden viele der bisherigen useEffect-Muster für Datenabruf durch Server Components und use() ersetzt. Der React Hook useEffect bleibt für Browser-APIs, externe Bibliotheken und Timer unverzichtbar.

4. useRef – DOM-Zugriff und stabile Werte ohne Re-Render

useRef liefert ein stabiles Objekt { current: value }, das sich über Re-Renders hinweg nicht ändert. Das macht ihn zum richtigen React Hook für zwei völlig verschiedene Anwendungsfälle: Erstens für direkten DOM-Zugriff, wenn man ein ref-Attribut an ein Element übergibt und dann programmatisch inputRef.current.focus() aufruft. Zweitens für Werte, die die Komponente intern verwenden soll, ohne dass eine Änderung einen Re-Render auslöst – etwa Timer-IDs, vorherige Werte oder Flags, die außerhalb des React-State-Systems leben sollen.

Ein häufiges Muster mit useRef: das Speichern des vorherigen Zustandswerts. Da useRef keinen Re-Render auslöst, kann man in useEffect nach jedem Render den aktuellen Wert in den Ref schreiben – beim nächsten Render ist ref.current dann der Wert des vorigen Renders. Dieser React Hook ist auch die richtige Wahl, wenn man in einem Callback-Kontext immer den neuesten State lesen will, ohne den Callback bei jeder Zustandsänderung neu erstellen zu müssen – man speichert den aktuellen State in einem Ref und liest ihn im Callback.

5. useContext – globalen Zustand teilen ohne Prop Drilling

useContext ist der React Hook für den Zugriff auf einen React Context. Er gibt den aktuellen Kontextwert zurück, der vom nächstliegenden Provider in der Komponentenhierarchie bereitgestellt wird. Das löst das Problem des Prop Drilling: Statt einen Wert durch fünf Komponentenebenen nach unten zu reichen, stellt man ihn einmal über einen Provider bereit und greift in jeder Kindkomponente direkt per useContext darauf zu. Der Hook löst bei jeder Änderung des Kontextwerts einen Re-Render aller konsumierenden Komponenten aus.

Das ist gleichzeitig die größte Schwäche von useContext: Wenn der Kontextwert ein Objekt ist, das sich bei jedem Render des Providers ändert, re-rendern alle Konsumenten unnötig. Das korrekte Muster: den Kontextwert mit useMemo stabilisieren oder den Context in separate, fein granulare Teile aufteilen – einen für häufig ändernde Daten, einen für stabile Aktionen. Als Entscheidungsregel gilt: useContext eignet sich für wenige Änderungen pro Sekunde, etwa Theme, Authentifizierung, Locale – nicht für hochfrequenten State wie Formularfelder oder Animations-Frames.


import { createContext, useContext, useMemo, useState, ReactNode } from 'react';

// Separate context for data and actions — avoids unnecessary re-renders
interface AuthContextType {
  user: { id: string; name: string } | null;
  isAuthenticated: boolean;
}
interface AuthActionsType {
  login: (credentials: { email: string; password: string }) => Promise<void>;
  logout: () => void;
}

const AuthContext = createContext<AuthContextType | null>(null);
const AuthActionsContext = createContext<AuthActionsType | null>(null);

export function AuthProvider({ children }: { children: ReactNode }) {
  const [user, setUser] = useState<{ id: string; name: string } | null>(null);

  // Stabilize the data object to prevent unnecessary re-renders
  const authData = useMemo<AuthContextType>(
    () => ({ user, isAuthenticated: user !== null }),
    [user]
  );

  // Actions never change — wrap in useMemo so consumers don't re-render
  const authActions = useMemo<AuthActionsType>(() => ({
    login: async (credentials) => {
      const response = await fetch('/api/auth/login', {
        method: 'POST',
        body: JSON.stringify(credentials),
      });
      const data = await response.json();
      setUser(data.user);
    },
    logout: () => setUser(null),
  }), []); // empty deps: these functions never need to change

  return (
    <AuthContext.Provider value={authData}>
      <AuthActionsContext.Provider value={authActions}>
        {children}
      </AuthActionsContext.Provider>
    </AuthContext.Provider>
  );
}

// Custom hooks encapsulate the useContext call with error boundary
export function useAuth() {
  const ctx = useContext(AuthContext);
  if (!ctx) throw new Error('useAuth must be used within AuthProvider');
  return ctx;
}

export function useAuthActions() {
  const ctx = useContext(AuthActionsContext);
  if (!ctx) throw new Error('useAuthActions must be used within AuthProvider');
  return ctx;
}

6. useMemo und useCallback – wann Memoizing wirklich hilft

useMemo und useCallback sind die am häufigsten überflüssig eingesetzten React Hooks. useMemo cached das Ergebnis einer Berechnungsfunktion zwischen Renders, solange sich die Dependencies nicht ändern. useCallback cached die Funktion selbst. Beide haben einen Overhead: das Erstellen des Dependency Arrays, die Vergleiche bei jedem Render und der Speicher für den Cache. Das lohnt sich nur dann, wenn die Berechnung oder das Erstellen der Funktion teurer ist als dieser Overhead – oder wenn die referenzielle Stabilität für untergeordnete Komponenten wichtig ist.

Die Entscheidungsregel für useMemo: Ist die Berechnung wirklich aufwändig – Filtern einer großen Liste, Aggregieren von Daten, komplexe Transformationen? Dann lohnt sich der React Hook. Für eine einfache Addition oder String-Formatierung ist useMemo Overhead ohne Nutzen. Die Entscheidungsregel für useCallback: Wird die Funktion als Prop an eine mit React.memo oder useMemo optimierte Kindkomponente übergeben? Oder ist sie eine Dependency in einem anderen useEffect oder useMemo? Dann macht sie referenzielle Stabilität. Sonst ist sie überflüssig. Mit dem React Compiler in React 19 übernimmt der Compiler automatisches Memoizing – die manuelle Nutzung dieser Hooks wird deutlich seltener notwendig.

7. useTransition und useDeferredValue – UI-Responsiveness sichern

useTransition ist der React Hook für Concurrent-Features in React 18 und 19. Er erlaubt es, State-Updates als nicht dringend zu markieren: startTransition(() => setFilterValue(input)). React kann diese Updates unterbrechen und priorisieren, während es dringende Updates – etwa die Anzeige des getippten Zeichens im Eingabefeld – sofort verarbeitet. Das Ergebnis: Eine Suche über eine große Liste fühlt sich für den Nutzer reaktionsschnell an, weil das Eingabefeld sofort reagiert, die gefilterte Liste aber asynchron nachgeliefert wird.

useDeferredValue ist der komplementäre React Hook: Statt den Update als nicht dringend zu markieren, erhält man eine "verzögerte" Version des Werts. Die Komponente rendert mit dem alten Wert, solange React noch am neuen Wert rechnet. Das eignet sich besonders, wenn man den Wert nicht selbst setzt, sondern von einem Elternteil empfängt – etwa als Prop. Beide Hooks arbeiten nur im Concurrent Mode und haben keinen Effekt in synchronen Render-Umgebungen. Sie sind das richtige Werkzeug, wenn aufwändige Renderings die UI blockieren, ohne dass der Nutzer auf das Ergebnis warten muss, bevor er weitertippt.


import { useState, useTransition, useDeferredValue, useMemo } from 'react';

// Large list filtering — useTransition keeps input responsive
function ProductSearch({ products }: { products: Product[] }) {
  const [query, setQuery] = useState('');
  const [isPending, startTransition] = useTransition();

  // Deferred value: React uses old value while computing new filtered list
  const deferredQuery = useDeferredValue(query);

  // Expensive computation runs with the deferred (potentially stale) value
  const filteredProducts = useMemo(
    () => products.filter(p =>
      p.name.toLowerCase().includes(deferredQuery.toLowerCase()) ||
      p.sku.includes(deferredQuery)
    ),
    [products, deferredQuery]
  );

  const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
    // Urgent update: immediately show what the user typed
    setQuery(e.target.value);

    // Non-urgent update: defer the navigation or heavy side-effect
    startTransition(() => {
      // e.g. update URL params or trigger a non-critical state change
      window.history.replaceState(null, '', `?q=${e.target.value}`);
    });
  };

  return (
    <div>
      <input value={query} onChange={handleSearch} placeholder="Suchen..." />
      {isPending && <span>Lädt...</span>}
      {/* Visually dim the list while a new result is computing */}
      <ul style={ { opacity: deferredQuery !== query ? 0.5 : 1 } }>
        {filteredProducts.map(p => <li key={p.id}>{p.name}</li>)}
      </ul>
    </div>
  );
}

8. useActionState – Formulare und Server Actions in React 19

useActionState ist der zentrale neue React Hook in React 19. Er verbindet eine Action-Funktion mit einem lokalen State und gibt drei Werte zurück: den aktuellen State, eine wrapped Action-Funktion und einen isPending-Boolean. Der Hook ist sowohl für Client- als auch für Server Actions konzipiert. Bei Server Actions läuft die Action-Funktion auf dem Server, der State wird nach dem Abschluss zurück an den Client übertragen, und React synchronisiert den Komponentenbaum automatisch. Das ersetzt das bisherige Muster aus manuellem useState für Ladezustand, useState für Fehlerzustand und einem onSubmit-Handler komplett.

Das Zusammenspiel mit useFormStatus ist wichtig: useFormStatus kann in einem Kindkomponent des Formulars verwendet werden und liefert den Pending-Zustand des übergeordneten Formular-Submits. So lässt sich ein Submit-Button deaktivieren, während eine Server Action läuft, ohne den Zustand nach unten zu reichen. Der React Hook useOptimistic ergänzt dieses Muster: Er zeigt sofort einen optimistischen Wert an, bevor die Server Action abgeschlossen ist, und stellt den vorherigen Wert wieder her, falls die Action fehlschlägt. Diese drei React Hooks zusammen bilden das vollständige Muster für progressive Formulare in React 19.

9. Alle React 19 Hooks im direkten Vergleich

Die Wahl des richtigen React Hooks ist keine Stilfrage. Falsche Entscheidungen führen zu unnötigen Re-Renders, schlechter Performance, schwer nachvollziehbaren Datenflüssen und Bugs durch veraltete Closure-Werte.

Hook Einsatzbereich Löst Re-Render aus? Typischer Fehler
useState Lokaler UI-Zustand einer Komponente Ja Stale-Closure statt funktionalem Update
useReducer Komplexer Zustand mit Aktionslogik Ja Für einfache Werte überdimensioniert
useEffect Seiteneffekte nach dem Render Nein Fehlende Cleanup-Funktion, falsche Deps
useRef DOM-Zugriff, stabile Werte ohne Render Nein Im Render-Body lesen (timing-Problem)
useMemo Teure Berechnung cachen Nein Overuse bei einfachen Berechnungen
useCallback Funktion referenziell stabil halten Nein Ohne React.memo-Kind wirkungslos
useTransition Updates als niedrige Priorität markieren Ja, verzögert Dringende UI-Updates verpackt
useActionState Formulare mit Server Actions (React 19) Ja Nur in React 19 verfügbar

Die Übersicht zeigt: Die meisten Bugs entstehen nicht durch einen unbekannten React Hook, sondern durch das Verwechseln ähnlicher Hooks. useRef statt useState wenn kein Re-Render gewollt ist, useCallback nur wenn die Funktion tatsächlich eine Dependency eines anderen Memoize-Hooks ist, useTransition statt keines Hooks wenn eine Filterung die UI blockiert – das sind die drei häufigsten Korrekturen, die Code-Reviews in React-Projekten zeigen.

Mironsoft

React-Entwicklung, Performance-Optimierung und Code-Reviews

React-Hooks-Probleme in bestehenden Projekten?

Wir analysieren React-Codebases auf falsch eingesetzte Hooks, unnötiges Memoizing, Stale-Closure-Bugs und Performance-Probleme – mit konkreten Empfehlungen und Refactoring-Plänen.

Hook-Audit

Analyse auf falsch eingesetzte React Hooks, Stale Closures und unnötiges Memoizing

React 19 Migration

Upgrade auf React 19, useActionState und Server Components einführen

Performance-Review

Re-Render-Analyse, Profiler-Auswertung und gezielte Optimierungen

10. Zusammenfassung

Das React 19 Hooks Cheatsheet zeigt: Jeder React Hook hat einen klar abgegrenzten Einsatzbereich. useState für lokalen UI-Zustand, der Re-Renders auslösen soll. useRef für stabile Werte und DOM-Zugriff ohne Re-Renders. useEffect für Seiteneffekte nach dem Render, immer mit Cleanup. useContext für selten ändernde globale Werte. useMemo und useCallback nur dort, wo die Memoize-Kosten den Vorteil überwiegen. useTransition für Concurrency und reaktionsschnelle UIs bei aufwändigen Updates.

React 19 ergänzt dieses Set mit useActionState für Server Actions und progressiven Formularen, useFormStatus für den Submit-Zustand in Kindkomponenten und useOptimistic für optimistische UI-Updates. Mit dem React Compiler übernimmt React außerdem automatisches Memoizing für die meisten Fälle – useMemo und useCallback werden dadurch seltener nötig, aber das Verständnis ihrer Semantik bleibt unverzichtbar für das Debugging und die Arbeit mit älteren Codebases. Wer alle React Hooks kennt und gezielt einsetzt, schreibt Komponenten, die performant, vorhersehbar und leicht testbar sind.

React 19 Hooks Cheatsheet — Das Wichtigste auf einen Blick

Zustand & Effekte

useState für lokalen Zustand mit Re-Render. useReducer für komplexe Zustandslogik. useEffect für Seiteneffekte, immer mit Cleanup-Funktion.

Referenzen & Context

useRef für DOM und stabile Werte ohne Re-Render. useContext für globale, selten ändernde Daten – Context mit useMemo stabilisieren.

Memoizing

useMemo nur für teure Berechnungen. useCallback nur wenn Funktion Dependency anderer Hooks oder Prop für optimierte Kinder ist. Mit React Compiler oft überflüssig.

React 19 Neue Hooks

useActionState für Server Actions und Formulare. useTransition für reaktionsschnelle UIs bei aufwändigen Updates. useOptimistic für optimistische Zustände.

11. FAQ: React 19 Hooks Cheatsheet

1Wann useState statt useRef?
useState wenn die Änderung einen Re-Render und aktualisierten Output auslösen soll. useRef für interne Werte ohne Auswirkung auf das Rendering.
2Warum ist useEffect so oft falsch eingesetzt?
Häufig für synchrone Transformationen verwendet, die in den Render-Body gehören. Fehlende Cleanup führt zu Memory Leaks. Nur für asynchrone Seiteneffekte und Browser-APIs gedacht.
3Wann lohnt sich useMemo wirklich?
Bei teuren Berechnungen wie dem Filtern großer Listen. Für einfache Werte ist der Overhead größer als der Nutzen. React Compiler übernimmt automatisches Memoizing in React 19.
4Was ist useActionState?
Neuer React-19-Hook für Formulare mit Server Actions. Verbindet Action-Funktion mit State, liefert aktuellen State, wrapped Action und isPending-Flag.
5useTransition vs. useDeferredValue?
useTransition wenn man selbst den State setzt und als nicht dringend markiert. useDeferredValue für einen Wert von außen, der verzögert verarbeitet werden soll.
6Wann useCallback verwenden?
Nur wenn die Funktion Prop für React.memo-Kind oder Dependency in useEffect/useMemo ist. Sonst erzeugt useCallback nur Overhead ohne Nutzen.
7Stale-Closure-Bugs vermeiden?
Funktionales Update-Muster: setValue(prev => prev + 1). Für Callbacks den aktuellen State in useRef spiegeln und aus dem Ref lesen.
8useContext für hochfrequenten State?
Nicht empfohlen. Jede Kontextwert-Änderung re-rendert alle Konsumenten. Für hochfrequenten State lokalen useState oder externen Store verwenden.
9React Compiler und useMemo/useCallback?
React Compiler fügt automatisches Memoizing ein. Manuelle useMemo/useCallback-Aufrufe werden in vielen Fällen überflüssig. Verständnis bleibt für Debugging und Legacy-Code wichtig.
10Custom Hooks korrekt testen?
Mit renderHook aus Testing Library. act() wrapping für State-Updates. Provider als wrapper-Option übergeben wenn useContext im Hook verwendet wird.