React State Management

6 Kernkonzepte
Die wichtigsten State-Management-Ansätze in React: useState · useReducer · useContext · Zustand · Redux · Redux Toolkit Von lokalem State bis zu globalem State-Management – dieser Cheatsheet bietet einen Überblick über die verschiedenen Ansätze, von eingebauten Hooks bis zu etablierten Bibliotheken.

useState – Lokaler State

const [state, setState] = useState(initial)
import { useState } from 'react'; function Counter() { const [count, setCount] = useState(0); return ( <button onClick={() => setCount(count + 1)}> { count } </button> ); }

useState ist der grundlegende Hook für lokalen State in funktionalen Komponenten. Er gibt einen aktuellen Wert und eine Setter-Funktion zurück, die das erneute Rendering auslöst.

Wichtige Regeln

Regel Beschreibung
Lokaler State Nur innerhalb der Komponente sichtbar
Immutabilität State nie direkt verändern – Setter verwenden
Funktionale Aktualisierung setCount(prev => prev + 1) für sichere Updates
Mehrere States Mehrere useState-Aufrufe für verschiedene Werte
Tipp: useState ist ideal für einfachen, lokal begrenzten State wie Eingabefelder, Toggle-Status oder Zähler. Bei komplexerem State oder globaler Nutzung sollten Sie andere Ansätze 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; } }

useReducer ist ein Hook für komplexen State mit mehreren Übergängen. Er ähnelt Redux, ist aber lokal auf eine Komponente beschränkt. Ideal für Formulare, Einkaufswagen oder andere Zustände mit vielen Aktionen.

Beispiele
// Reducer für Todo-Liste
function todoReducer(state, action) {
switch (action.type) {
case 'ADD_TODO':
return [...state, { id: Date.now(), text: action.payload, done: false }];
case 'TOGGLE_TODO':
return state.map(todo =>
todo.id === action.payload
? { ...todo, done: !todo.done }
: todo
);
case 'REMOVE_TODO':
return state.filter(todo => todo.id !== action.payload);
default:
return state;
}
}
// In der Komponente
const [todos, dispatch] = useReducer(todoReducer, []);
// Aktionen auslösen
dispatch({ type: 'ADD_TODO', payload: 'Neue Aufgabe' });
dispatch({ type: 'TOGGLE_TODO', payload: todoId });
Tipp: useReducer ist eine gute Wahl, wenn der State mehrere Unterwerte oder komplexe Übergänge hat. Er macht den State-Update-Logik testbarer und wartbarer als mehrere useState-Aufrufe.

useContext – Globaler State mit Context

createContext · Provider · useContext
// Context erstellen const ThemeContext = createContext('light'); // Provider in Elternkomponente <ThemeContext.Provider value={ 'dark' }> <App /> </ThemeContext.Provider> // In Kindkomponente const theme = useContext(ThemeContext);

useContext ermöglicht den Zugriff auf Context-Werte, ohne Props durch mehrere Ebenen zu leiten (Prop Drilling). Ideal für Theme, Sprache, Benutzerinformationen oder andere globale Daten.

Beispiele
// Context mit State kombiniert
const UserContext = createContext();
function UserProvider({ children }) {
const [user, setUser] = useState(null);
return (
<UserContext.Provider value={{ user, setUser }}>
{ children }
</UserContext.Provider>
);
}
// In beliebiger Komponente
function Profile() {
const { user, setUser } = useContext(UserContext);
return (
<div>
{ user ? `Willkommen ${user.name}` : "Bitte einloggen" }
<button onClick={() => setUser({ name: "Anna" })}>Login</button>
</div>
);
}
Tipp: Context ist für Werte geeignet, die sich selten ändern (wie Theme oder Sprache). Bei häufig wechselnden Daten ist eine State-Management-Bibliothek wie Zustand oder Redux oft die bessere Wahl.

Zustand – Einfacher globaler State

create · set · get · immer
// store.js import { create } from 'zustand'; export const useStore = create((set) => ({ count: 0, increment: () => set((state) => ({ count: state.count + 1 })), decrement: () => set((state) => ({ count: state.count - 1 })), }));

Zustand ist eine schlanke State-Management-Bibliothek mit minimaler API. Sie ist einfach zu bedienen, benötigt keinen Provider und funktioniert sowohl in React als auch außerhalb.

Beispiele
// Store mit mehreren Werten
export const useUserStore = create((set, get) => ({
user: null,
isLoading: false,
login: async (credentials) => {
set({ isLoading: true });
try {
const user = await api.login(credentials);
set({ user, isLoading: false });
} catch (error) {
set({ isLoading: false });
throw error;
}
},
logout: () => set({ user: null }),
getUser: () => get().user,
}));
// In Komponente
function Profile() {
const { user, login, logout } = useUserStore();
// Oder nur bestimmte Werte selektieren
const userName = useUserStore((state) => state.user?.name);
return <div>...</div>;
}
Tipp: Zustand ist eine großartige Alternative zu Redux für kleinere bis mittelgroße Anwendungen. Die API ist minimalistisch und die Leistung ist hervorragend durch automatische Selektion.

Redux & Redux Toolkit – Branchenstandard

configureStore · createSlice · useSelector · useDispatch
// store.js mit Redux Toolkit import { configureStore, createSlice } from '@reduxjs/toolkit'; const counterSlice = createSlice({ name: 'counter', initialState: { value: 0 }, reducers: { increment: (state) => { state.value += 1; }, decrement: (state) => { state.value -= 1; }, } }); export const { increment, decrement } = counterSlice.actions; export const store = configureStore({ reducer: { counter: counterSlice.reducer } });

Redux ist die etablierteste State-Management-Lösung für React. Redux Toolkit (RTK) ist der offizielle, moderne Wrapper, der Boilerplate reduziert und Best Practices fördert.

Beispiele
// Slice für API-Daten
import { createAsyncThunk } from '@reduxjs/toolkit';
// Async Thunk
export const fetchUsers = createAsyncThunk('users/fetch', async () => {
const response = await fetch('/api/users');
return await response.json();
});
// Slice mit extraReducers
const usersSlice = createSlice({
name: 'users',
initialState: { data: [], status: 'idle', error: null },
reducers: {},
extraReducers: (builder) => {
builder
.addCase(fetchUsers.pending, (state) => { state.status = 'loading'; })
.addCase(fetchUsers.fulfilled, (state, action) => {
state.status = 'succeeded';
state.data = action.payload;
})
.addCase(fetchUsers.rejected, (state, action) => {
state.status = 'failed';
state.error = action.error.message;
});
}
});
// In Komponente
import { useSelector, useDispatch } from 'react-redux';
const dispatch = useDispatch();
const users = useSelector((state) => state.users.data);
const status = useSelector((state) => state.users.status);
useEffect(() => {
dispatch(fetchUsers());
}, [dispatch]);
Tipp: Für neue Projekte wird Redux Toolkit dringend empfohlen. Es reduziert den Boilerplate-Code erheblich und macht Redux wieder angenehm zu verwenden.

State Management im Überblick

useState Lokaler State
Einfach, komponentenintern
useReducer Komplexer State
Mit Aktionen & Reducer
useContext Globaler State
Prop Drilling vermeiden
Zustand Leichter globaler State
Minimalistisch, schnell
Redux Branchenstandard
Vorhersagbar, testbar
RTK Redux Toolkit
Modern, weniger Boilerplate

Quick Summary

useState
Lokaler State
useReducer
Reducer-State
useContext
Globaler Context
Zustand
Einfacher globaler State
Redux
Branchenstandard
RTK
Redux Toolkit
useState · useReducer · useContext · Zustand · Redux Toolkit