React Hooks & Lifecycle

6 Kern-Hooks
Die wichtigsten React-Hooks für State, Lifecycle und Performance: useState · useEffect · useContext · useReducer · useRef · useMemo / useCallback Hooks ermöglichen die Nutzung von State und Lebenszyklus-Funktionen in funktionalen Komponenten. Diese Cheatsheet fasst die wichtigsten Hooks mit Syntax und praktischen Beispielen zusammen.

useState – State in funktionalen Komponenten

const [state, setState] = useState(initialValue)
import { useState } from 'react'; const [count, setCount] = useState(0); const [user, setUser] = useState({ name: '', age: 0 });

useState ist der grundlegendste Hook für die Verwaltung von lokalem State in funktionalen Komponenten. Er gibt einen aktuellen Wert und eine Setter-Funktion zurück.

Wichtige useState-Patterns

Pattern Beschreibung
const [state, setState] = useState(0) Primitiver Wert (number, string, boolean)
const [state, setState] = useState({}) Objekt-State (mit Spread-Operator updaten)
const [state, setState] = useState([]) Array-State (mit Spread-Operator updaten)
setState(prev => prev + 1) Funktionale Aktualisierung (bei Abhängigkeit vom vorherigen Wert)
useState(() => expensiveComputation()) Lazy Initialisierung (nur einmal beim ersten Rendern)
Beispiele
// Einfacher Counter
const [count, setCount] = useState(0);
<button onClick={() => setCount(count + 1)}>
{ count }
</button>
// Objekt-State mit Spread
const [form, setForm] = useState({ name: '', email: '' });
const handleChange = (e) => {
setForm({ ...form, [e.target.name]: e.target.value });
};
// Lazy Initialisierung
const [data, setData] = useState(() => {
return expensiveComputation();
});
Tipp: Bei Objekten oder Arrays immer eine neue Referenz erstellen (z.B. mit Spread-Operator), damit React die Änderung erkennt und ein erneutes Rendern auslöst.

useEffect – Seiteneffekte & Lifecycle

useEffect(callback, [dependencies])
import { useEffect } from 'react'; useEffect(() => { // Seiteneffekt ausführen console.log('Component mounted or updated'); return () => { // Cleanup (optional) console.log('Cleanup'); }; }, [dependency]); // Nur bei Änderung von dependency

useEffect führt Seiteneffekte wie API-Aufrufe, DOM-Manipulationen oder das Setzen von Timern aus. Das Abhängigkeits-Array steuert, wann der Effekt erneut ausgeführt wird.

useEffect-Varianten

Variante Beschreibung
useEffect(() => {}) Nach jedem Rendering (selten verwendet)
useEffect(() => {}, []) Einmal beim Mounten (wie componentDidMount)
useEffect(() => {}, [dep]) Bei Änderung von dep (wie componentDidUpdate für dep)
useEffect(() => { return cleanup }, []) Mit Cleanup beim Unmounten
Beispiele
// API-Aufruf beim Mounten
useEffect(() => {
fetch('https://api.example.com/data')
.then(res => res.json())
.then(setData);
}, []);
// Timer mit Cleanup
useEffect(() => {
const interval = setInterval(() => {
setCount((c) => c + 1);
}, 1000);
return () => clearInterval(interval);
}, []);
// Effekt bei Änderung von props
useEffect(() => {
console.log(`User ID geändert: ${userId}`);
fetchUser(userId);
}, [userId]);
// Event-Listener mit Cleanup
useEffect(() => {
const handleResize = () => setWidth(window.innerWidth);
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
Tipp: Das Abhängigkeits-Array sollte alle Werte enthalten, die im Effekt verwendet werden. Mit ESLint-Plugin eslint-plugin-react-hooks können Sie fehlende Abhängigkeiten automatisch prüfen.

useContext – Globale Daten ohne Prop Drilling

const value = useContext(MyContext)
// Context definieren import { createContext, useContext } from 'react'; export const ThemeContext = createContext('light'); // In Komponente const theme = useContext(ThemeContext);

useContext ermöglicht den Zugriff auf Context-Werte ohne Prop Drilling. Context ist ideal für Themen, Sprach-Einstellungen, Benutzerinformationen und andere globale Daten.

Beispiele
// ThemeContext definieren
import { createContext, useContext, useState } from 'react';
export const ThemeContext = createContext();
// Provider-Komponente
export function ThemeProvider({ children }) {
const [theme, setTheme] = useState('light');
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
{ children }
</ThemeContext.Provider>
);
}
// useContext in beliebiger Komponente
function ThemedButton() {
const { theme, setTheme } = useContext(ThemeContext);
return (
<button
onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}
>
Aktuelles Theme: { theme }
</button>
);
}
Tipp: Context ist ideal für Werte, die sich selten ändern (wie Themes, Sprach-Einstellungen). Für häufige Änderungen sollten Sie State-Management wie Redux oder Zustand in Betracht ziehen.

useReducer – Komplexer State mit Reducer

const [state, dispatch] = useReducer(reducer, initialState)
// Reducer-Funktion function counterReducer(state, action) { switch (action.type) { case 'increment': return { count: state.count + 1 }; case 'decrement': return { count: state.count - 1 }; default: return state; } } const [state, dispatch] = useReducer(counterReducer, { count: 0 }); dispatch({ type: 'increment' });

useReducer ist eine Alternative zu useState für komplexen State mit mehreren abhängigen Werten oder wenn die nächste State-Änderung vom vorherigen State abhängt. Er ähnelt Redux, aber innerhalb einer Komponente.

Beispiele
// Todo-Liste mit useReducer
function todoReducer(state, action) {
switch (action.type) {
case 'add':
return [...state, { id: Date.now(), text: action.payload, completed: false }];
case 'toggle':
return state.map(todo =>
todo.id === action.payload
? { ...todo, completed: !todo.completed }
: todo
);
case 'delete':
return state.filter(todo => todo.id !== action.payload);
default: return state;
}
}
// useReducer in Komponente
const [todos, dispatch] = useReducer(todoReducer, []);
dispatch({ type: 'add', payload: 'Neue Aufgabe' });
Tipp: useReducer ist besonders nützlich für State mit komplexen Übergängen, wie Todo-Listen, Formulare mit vielen Feldern oder Zustände mit vielen Aktionen.

useRef – DOM-Referenzen & mutable Werte

const ref = useRef(initialValue)
// DOM-Referenz const inputRef = useRef(null); useEffect(() => { inputRef.current.focus(); }, []); <input ref={ inputRef } /> // Mutable Werte (ohne erneutes Rendern) const countRef = useRef(0); countRef.current++;

useRef erstellt eine mutable Referenz, die über die gesamte Lebensdauer der Komponente erhalten bleibt. Sie wird entweder für DOM-Referenzen oder für mutable Werte verwendet, die kein erneutes Rendern auslösen sollen.

Beispiele
// DOM-Referenz für Fokus
const inputRef = useRef(null);
useEffect(() => {
inputRef.current.focus();
}, []);
<input ref={ inputRef } />
// Wert ohne erneutes Rendern speichern
const renderCount = useRef(0);
useEffect(() => {
renderCount.current++;
});
// Vorherigen Wert speichern (usePrevious)
function usePrevious(value) {
const ref = useRef();
useEffect(() => {
ref.current = value;
}, [value]);
return ref.current;
}
Tipp: useRef ist ideal für Werte, die über Rendering-Grenzen hinweg erhalten bleiben sollen, aber kein erneutes Rendering auslösen – z.B. Timer-IDs, vorherige Werte oder DOM-Referenzen.

useMemo & useCallback – Performance optimieren

useMemo(compute, [deps]) · useCallback(fn, [deps])
// useMemo – Wert memoized const expensiveValue = useMemo(() => { return expensiveComputation(a, b); }, [a, b]); // useCallback – Funktion memoized const handleClick = useCallback(() => { console.log(count); }, [count]);

useMemo und useCallback optimieren die Performance, indem sie Werte oder Funktionen zwischenspeichern (memoizen) und nur bei Änderung der Abhängigkeiten neu berechnen.

useMemo vs useCallback

Hook Rückgabewert Verwendung
useMemo Wert (beliebiger Typ) Teure Berechnungen, Filterungen
useCallback Memoized Funktion Event-Handler, die an Kindkomponenten weitergegeben werden
Beispiele
// useMemo – Große Liste filtern
const filteredItems = useMemo(() => {
return items.filter(item =>
item.name.includes(searchTerm)
);
}, [items, searchTerm]);
// useMemo – Teure Berechnung
const total = useMemo(() => {
return items.reduce((sum, item) => sum + item.price, 0);
}, [items]);
// useCallback – Event-Handler für Kindkomponente
const onSave = useCallback((data) => {
console.log('Saving...', data);
saveData(data);
}, [saveData]);
<SaveButton onSave={ onSave } />
// useCallback mit Abhängigkeiten
const handleSearch = useCallback(() => {
setFilteredItems(items.filter(item =>
item.name.includes(searchTerm)
));
}, [items, searchTerm]);
Tipp: Verwenden Sie useMemo und useCallback nur, wenn die Berechnung wirklich teuer ist oder eine Kindkomponente davon profitiert. Over-Optimierung kann den Code unlesbar machen.

React Hooks im Überblick

useState Lokaler State
const [state, setState] = useState(0)
useEffect Seiteneffekte
API-Aufrufe, DOM, Timer
useContext Globaler State
Themen, Benutzer, Sprache
useReducer Komplexer State
Reducer-Pattern
useRef DOM & mutable Werte
focus, vorherige Werte
useMemo Performance
Werte memoizen

Quick Summary

useState
State
useEffect
Seiteneffekte
useContext
Globaler State
useReducer
Reducer
useRef
Referenzen
useMemo
Performance
useEffect(() => { ... }, [deps]) · useContext(MyContext) · useReducer(reducer, initialState)