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.
Inhaltsverzeichnis
- 1. Warum React Hooks das Komponentenmodell verändert haben
- 2. useState – lokaler Zustand einfach und sicher verwalten
- 3. useEffect – Seiteneffekte richtig koordinieren
- 4. useRef – DOM-Zugriff und stabile Werte ohne Re-Render
- 5. useContext – globalen Zustand teilen ohne Prop Drilling
- 6. useMemo und useCallback – wann Memoizing wirklich hilft
- 7. useTransition und useDeferredValue – UI-Responsiveness sichern
- 8. useActionState – Formulare und Server Actions in React 19
- 9. Alle React 19 Hooks im direkten Vergleich
- 10. Zusammenfassung
- 11. FAQ
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.