Appearance
Kapitel 11: Zustandsverwaltung
In größeren Anwendungen wird Zustandsverwaltung unerlässlich, um Daten zwischen Komponenten zu teilen.
11.1 Warum Zustandsverwaltung?
🤔 Problem ohne Zustandsverwaltung
App
├── Header (benötigt user-State)
├── Main (benötigt user-State)
└── Footer (benötigt user-State)Problem: Jede Komponente benötigt den gleichen State → Props-Drilling.
✅ Lösung: Zustandsverwaltung
- State wird global gespeichert
- Alle Komponenten können darauf zugreifen
11.2 Drei Lösungsansätze
1️⃣ useReducer + useContext (Leichtgewichtig)
Geeignet für: Kleine bis mittlere Projekte
Vorteile:
- Keine zusätzliche Bibliothek erforderlich
- Einfach zu verstehen
Nachteile:
- Schwer zu skalieren
- Keine "Time Travel" Debugging
2️⃣ Redux Toolkit (RTK) - Offiziell empfohlen
Geeignet für: Große Projekte mit komplexem State
Vorteile:
- Offiziell von Redux-Team empfohlen
- Vereinfacht traditionelles Redux
- Hervorragendes DevTools
Nachteile:
- Steile Lernkurve
- Mehr Boilerplate-Code
3️⃣ Zustand - Leichtgewichtig und einfach
Geeignet für: Mittlere Projekte, die Einfachheit bevorzugen
Vorteile:
- Sehr einfach und intuitiv
- Wenig Boilerplate-Code
- Gute Performance
Nachteile:
- Kleinere Community als Redux
- Weniger Tutorials
11.3 Lösung 1: useReducer + useContext
📦 Store erstellen
store.js:
jsx
import { createContext, useContext, useReducer } from 'react';
// 1. Initialzustand
const initialState = {
user: null,
isLoggedIn: false
};
// 2. Reducer-Funktion
function reducer(state, action) {
switch (action.type) {
case 'LOGIN':
return { ...state, user: action.payload, isLoggedIn: true };
case 'LOGOUT':
return { ...state, user: null, isLoggedIn: false };
default:
return state;
}
}
// 3. Context erstellen
const StoreContext = createContext();
// 4. Provider-Komponente
export function StoreProvider({ children }) {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<StoreContext.Provider value={{ state, dispatch }}>
{children}
</StoreContext.Provider>
);
}
// 5. Custom Hook für einfachen Zugriff
export function useStore() {
return useContext(StoreContext);
}🏠 Store in App verwenden
App.jsx:
jsx
import { StoreProvider } from './store';
function App() {
return (
<StoreProvider>
<Header />
<Main />
</StoreProvider>
);
}📥 State in Komponenten verwenden
Header.jsx:
jsx
import { useStore } from './store';
function Header() {
const { state, dispatch } = useStore();
return (
<div>
{state.isLoggedIn ? (
<>
<p>Willkommen, {state.user.name}!</p>
<button onClick={() => dispatch({ type: 'LOGOUT' })}>
Logout
</button>
</>
) : (
<button onClick={() => dispatch({ type: 'LOGIN', payload: { name: 'Max' } })}>
Login
</button>
)}
</div>
);
}11.4 Lösung 2: Redux Toolkit (RTK)
📦 Installation
bash
# npm
npm install @reduxjs/toolkit react-redux
# pnpm (empfohlen)
pnpm add @reduxjs/toolkit react-redux🔧 Konfiguration (Schritt für Schritt)
Schritt 1: Slice erstellen
userSlice.js:
jsx
import { createSlice } from '@reduxjs/toolkit';
const userSlice = createSlice({
name: 'user',
initialState: {
user: null,
isLoggedIn: false
},
reducers: {
login: (state, action) => {
state.user = action.payload;
state.isLoggedIn = true;
},
logout: (state) => {
state.user = null;
state.isLoggedIn = false;
}
}
});
export const { login, logout } = userSlice.actions;
export default userSlice.reducer;Schritt 2: Store konfigurieren
store.js:
jsx
import { configureStore } from '@reduxjs/toolkit';
import userReducer from './userSlice';
export const store = configureStore({
reducer: {
user: userReducer
}
});Schritt 3: Provider bereitstellen
App.jsx:
jsx
import { Provider } from 'react-redux';
import { store } from './store';
function App() {
return (
<Provider store={store}>
<Header />
<Main />
</Provider>
);
}Schritt 4: State verwenden
Header.jsx:
jsx
import { useSelector, useDispatch } from 'react-redux';
import { login, logout } from './userSlice';
function Header() {
const user = useSelector((state) => state.user.user);
const isLoggedIn = useSelector((state) => state.user.isLoggedIn);
const dispatch = useDispatch();
return (
<div>
{isLoggedIn ? (
<>
<p>Willkommen, {user.name}!</p>
<button onClick={() => dispatch(logout())}>Logout</button>
</>
) : (
<button onClick={() => dispatch(login({ name: 'Max' }))}>
Login
</button>
)}
</div>
);
}11.5 Lösung 3: Zustand
📦 Installation
bash
# npm
npm install zustand
# pnpm (empfohlen)
pnpm add zustand🔧 Store erstellen
store.js:
javascript
import { create } from 'zustand';
export const useStore = create((set) => ({
user: null,
isLoggedIn: false,
login: (user) => set({ user, isLoggedIn: true }),
logout: () => set({ user: null, isLoggedIn: false })
}));📥 State verwenden
Header.jsx:
jsx
import { useStore } from './store';
function Header() {
const { user, isLoggedIn, login, logout } = useStore();
return (
<div>
{isLoggedIn ? (
<>
<p>Willkommen, {user.name}!</p>
<button onClick={logout}>Logout</button>
</>
) : (
<button onClick={() => login({ name: 'Max' })}>
Login
</button>
)}
</div>
);
}Vorteile von Zustand:
- Kein Provider-Wrapper erforderlich
- Sehr einfach zu verwenden
- Gute Performance
11.6 Zustandspersistenz (LocalStorage)
💾 State in LocalStorage speichern
Beispiel mit Zustand:
javascript
import { create } from 'zustand';
import { persist } from 'zustand/middleware';
export const useStore = create(
persist(
(set) => ({
user: null,
isLoggedIn: false,
login: (user) => set({ user, isLoggedIn: true }),
logout: () => set({ user: null, isLoggedIn: false })
}),
{
name: 'user-storage', // LocalStorage-Schlüssel
}
)
);Beispiel mit Redux Toolkit:
javascript
// store.js
import { configureStore } from '@reduxjs/toolkit';
import { persistStore, persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
const persistConfig = {
key: 'root',
storage
};
const persistedReducer = persistReducer(persistConfig, userReducer);
export const store = configureStore({
reducer: persistedReducer
});
export const persistor = persistStore(store);📝 Zusammenfassung
In diesem Kapitel haben wir gelernt:
- ✅ Warum Zustandsverwaltung wichtig ist
- ✅ Drei Lösungsansätze (useReducer+useContext, RTK, Zustand)
- ✅ useReducer + useContext (leichtgewichtig)
- ✅ Redux Toolkit (RTK) Installation und Verwendung
- ✅ Zustand (einfach und leichtgewichtig)
- ✅ Zustandspersistenz (LocalStorage)
🎯 Nächste Schritte
Im nächsten Kapitel werden wir lernen:
- Netzwerk-Anfragen mit axios
- API-Calls in React
- Daten abrufen und anzeigen
Bereit für Netzwerk-Anfragen? → Kapitel 12: Netzwerk-Anfragen
