Zustand vs. Redux: State-Manager für Gesundheits-Apps
Technischer Vergleich von Zustand und Redux Toolkit für React: Wir analysieren Boilerplate, komplexe Daten, Leistung und Offline-Sync für Ihre Gesundheits-App.
Auf dieser Seite
Ein modernes Gesundheits-Dashboard in React aufzubauen erfordert eine sorgfältige Überlegung zum State-Management. Sie haben es nicht nur mit einfachen UI-Schaltern zu tun; Sie verarbeiten sensible Nutzerdaten, komplexe Datenstrukturen von Wearables und den entscheidenden Bedarf an Funktionen wie dem Offline-Zugriff. Die Wahl der richtigen State-Management-Bibliothek ist eine grundlegende Entscheidung, die Leistung, Skalierbarkeit und Wartbarkeit Ihrer App beeinflusst.
In diesem Artikel gehen wir auf einen technischen Vergleich zweier der beliebtesten State-Management-Lösungen im React-Ökosystem ein: Zustand und Redux Toolkit (RTK). Wir analysieren sie aus der Perspektive des Aufbaus eines Gesundheits-Dashboards und konzentrieren uns auf:
- Boilerplate und Developer Experience: Wie schnell können Sie loslegen?
- Komplexe Gesundheitsdaten verwalten: Wie gehen sie mit normalisierten und relationalen Daten um?
- Leistung: Welche Lösung eignet sich besser für Echtzeit-Updates von Gesundheitsgeräten?
- Offline-Synchronisierung: Wie können wir einen „Offline-first“-Ansatz für unsere Gesundheits-App umsetzen?
Am Ende haben Sie ein klares Verständnis der Stärken und Schwächen jeder Bibliothek, ergänzt durch praxisnahe Codebeispiele, damit Sie für Ihr nächstes Health-Tech-Projekt eine fundierte Entscheidung treffen können.
Das Problem verstehen: State-Management in einer Gesundheits-App
Ein Gesundheits-Dashboard stellt besondere Anforderungen an das State-Management:
- Komplexe, normalisierte Daten: Wir müssen Nutzerprofile, eine Sammlung verbundener Geräte und Zeitreihendaten für verschiedene Gesundheitskennzahlen (Herzfrequenz, Schritte, Schlaf usw.) verwalten.
- Echtzeit-Updates: Die App muss möglicherweise häufige Updates von einem verbundenen Wearable über WebSockets oder eine vergleichbare Technologie verarbeiten.
- Offline-Funktionalität: Eine Nutzerin oder ein Nutzer sollte Daten eingeben oder vorhandene Daten auch ohne Internetverbindung ansehen können. Die App muss sich nahtlos synchronisieren, sobald sie wieder online ist.
- Leistung: Bei potenziell großen Datensätzen und Echtzeit-Updates müssen wir unnötige Re-Renders vermeiden, damit die Benutzeroberfläche flüssig und reaktionsschnell bleibt.
Architektur des State-Management-Vergleichs
Das folgende Diagramm zeigt, wie beide Bibliotheken den State einer Gesundheits-App handhaben:
Voraussetzungen
- Ein solides Verständnis von React und Hooks.
- Node.js und npm/yarn sind installiert.
- Vertrautheit mit grundlegenden State-Management-Konzepten in React.
Richten wir ein neues React-Projekt ein, um unsere Beispiele aufzubauen:
npx create-react-app health-app --template typescript
cd health-app
Sehen wir uns nun an, wie Zustand und Redux Toolkit diese Herausforderungen angehen.
Boilerplate und Ersteinrichtung vergleichen
Was wir tun
Wir erstellen mit beiden Bibliotheken einen einfachen Store, um die Profilinformationen einer Nutzerin oder eines Nutzers zu verwalten. So erhalten wir einen ersten Eindruck vom Unterschied bei Boilerplate und Einrichtung.
Zustand: minimalistisch und hook-basiert
Zustand ist für seine Einfachheit und minimale API bekannt. Sie können einen globalen Store mit nur wenigen Codezeilen erstellen.
Installation:
npm install zustand
Den User-Store erstellen (src/stores/userStore.ts):
// src/stores/userStore.ts
import { create } from 'zustand';
interface UserProfile {
name: string;
age: number;
email: string;
}
interface UserState {
profile: UserProfile | null;
setUserProfile: (profile: UserProfile) => void;
clearUserProfile: () => void;
}
export const useUserStore = create<UserState>((set) => ({
profile: null,
setUserProfile: (profile) => set({ profile }),
clearUserProfile: () => set({ profile: null }),
}));
Redux Toolkit: strukturiert und meinungsstark
Redux Toolkit (RTK) ist der offizielle, empfohlene Weg, Redux-Logik zu schreiben. Es vereinfacht die traditionell umfangreiche Redux-Einrichtung mit Werkzeugen wie configureStore und createSlice.
Installation:
npm install @reduxjs/toolkit react-redux
Das User-Slice erstellen (src/features/user/userSlice.ts):
// src/features/user/userSlice.ts
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import type { RootState } from '../../app/store';
interface UserProfile {
name: string;
age: number;
email: string;
}
interface UserState {
profile: UserProfile | null;
}
const initialState: UserState = {
profile: null,
};
const userSlice = createSlice({
name: 'user',
initialState,
reducers: {
setUserProfile: (state, action: PayloadAction<UserProfile>) => {
state.profile = action.payload;
},
clearUserProfile: (state) => {
state.profile = null;
},
},
});
export const { setUserProfile, clearUserProfile } = userSlice.actions;
export const selectUserProfile = (state: RootState) => state.user.profile;
export default userSlice.reducer;
Den Store konfigurieren (src/app/store.ts):
// src/app/store.ts
import { configureStore } from '@reduxjs/toolkit';
import userReducer from '../features/user/userSlice';
export const store = configureStore({
reducer: {
user: userReducer,
},
});
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
So funktioniert es
- Zustand: Erstellt direkt einen benutzerdefinierten Hook (
useUserStore). Es ist kein Context-Provider erforderlich, der Ihre Anwendung umschließt. State-Updates erfolgen über dieset-Funktion, die imcreate-Callback bereitgestellt wird. - Redux Toolkit: Verwendet
createSlice, um Actions und einen Reducer für einen bestimmten Teil des States zu erzeugen. Diese Reducer werden anschließend mitconfigureStorein einem einzigen globalen Store zusammengeführt. Ihre Anwendung muss in eine<Provider>-Komponente eingebunden werden.
Fazit zum Boilerplate
Zustand ist beim minimalen Boilerplate klar im Vorteil. Die Einrichtung geht schneller und erfordert weniger Dateien und Konzepte, um zu beginnen. Redux Toolkit ist gegenüber klassischem Redux zwar deutlich verbessert, bringt aber mit Slice- und Store-Konfiguration weiterhin mehr „Zeremonie“ mit sich.
Komplexe Datenstrukturen für Gesundheitskennzahlen verwalten
Was wir tun
Unsere Gesundheits-App muss eine Sammlung von Gesundheitskennzahlen verwalten, die sich als normalisierter Datensatz verstehen lässt. Wir sehen uns an, wie beide Bibliotheken mit diesem häufigen Szenario umgehen.
Redux Toolkit: createEntityAdapter zur Normalisierung
RTK überzeugt bei der Verwaltung normalisierter Daten. createEntityAdapter ist ein leistungsstarkes Hilfsmittel, das vorgefertigte Reducer und Selektoren für CRUD-Operationen auf einer normalisierten State-Struktur bereitstellt.
Das Metrics-Slice erstellen (src/features/metrics/metricsSlice.ts):
// src/features/metrics/metricsSlice.ts
import {
createSlice,
createEntityAdapter,
PayloadAction,
} from '@reduxjs/toolkit';
import type { RootState } from '../../app/store';
export interface HealthMetric {
id: string; // e.g., 'heart-rate-2023-12-25T10:00:00Z'
type: 'heartRate' | 'steps' | 'sleep';
value: number;
timestamp: string;
}
const metricsAdapter = createEntityAdapter<HealthMetric>({
sortComparer: (a, b) => b.timestamp.localeCompare(a.timestamp),
});
const initialState = metricsAdapter.getInitialState({
status: 'idle',
error: null as string | null,
});
const metricsSlice = createSlice({
name: 'metrics',
initialState,
reducers: {
addMetric: metricsAdapter.addOne,
addMetrics: metricsAdapter.addMany,
updateMetric: metricsAdapter.updateOne,
},
});
export const { addMetric, addMetrics, updateMetric } = metricsSlice.actions;
export const {
selectAll: selectAllMetrics,
selectById: selectMetricById,
} = metricsAdapter.getSelectors((state: RootState) => state.metrics);
export default metricsSlice.reducer;
Zustand: Slices für Modularität nutzen
Zustand hat zwar kein eingebautes Gegenstück zu createEntityAdapter, Sie können jedoch ein vergleichbares Maß an Organisation erreichen, indem Sie das „Slice-Muster“ verwenden. Dabei erstellen Sie getrennte State-Slices und führen sie in einem einzigen Store zusammen.
Einen Metrics-Store mit Slices erstellen (src/stores/rootStore.ts):
// src/stores/rootStore.ts
import { create } from 'zustand';
import { UserState, useUserStore } from './userStore';
export interface HealthMetric {
id: string;
type: 'heartRate' | 'steps' | 'sleep';
value: number;
timestamp: string;
}
interface MetricsState {
metrics: Record<string, HealthMetric>;
addMetric: (metric: HealthMetric) => void;
// ... other metric actions
}
const createMetricsSlice = (set: any) => ({
metrics: {},
addMetric: (metric: HealthMetric) =>
set((state: { metrics: { metrics: any; }; }) => ({
metrics: {
...state.metrics.metrics,
[metric.id]: metric,
},
})),
});
// We can combine slices, although for this example we'll keep them separate
// to show how Zustand encourages modularity.
// const useRootStore = create((...a) => ({
// ...useUserStore(...a),
// ...createMetricsSlice(...a),
// }));
// For simplicity, we'll create a separate metrics store
export const useMetricsStore = create<MetricsState>(createMetricsSlice);
So funktioniert es
- Redux Toolkit:
createEntityAdaptererzeugt automatisch die Form des States ({ ids: [], entities: {} }) sowie Reducer wieaddOne,addManyundupdateOne, was die Arbeit mit Datensammlungen vereinfacht. - Zustand: Sie müssen Form des States und Aktualisierungslogik selbst definieren. Das ist aufwendiger, gibt Ihnen aber volle Flexibilität. Das Slice-Muster hilft, den Store mit wachsendem Umfang übersichtlich zu halten.
Fazit zu komplexen Daten
Redux Toolkit hat hier bei stark strukturierten, relationalen Daten einen klaren Vorteil. createEntityAdapter setzt bewährte Praktiken der Datennormalisierung durch und erspart Ihnen das Schreiben wiederholter CRUD-Logik. Zustand ist durchaus geeignet, erfordert jedoch, dass Sie diese Logik selbst aufbauen.
Offline-Synchronisierung mit Persistence-Middleware umsetzen
Eine zentrale Funktion einer Gesundheits-App ist die Fähigkeit, offline zu arbeiten. Beide Bibliotheken können dies mit Middleware erreichen, die den State des Stores im lokalen Speicher persistiert.
Zustand: persist-Middleware
Zustand bietet eine klare und einfache persist-Middleware.
Den User-Store für die Persistenz aktualisieren (src/stores/userStore.ts):
// src/stores/userStore.ts
import { create } from 'zustand';
import { persist, createJSONStorage } from 'zustand/middleware';
// ... (interfaces remain the same)
export const useUserStore = create(
persist<UserState>(
(set) => ({
profile: null,
setUserProfile: (profile) => set({ profile }),
clearUserProfile: () => set({ profile: null }),
}),
{
name: 'user-storage', // unique name
storage: createJSONStorage(() => localStorage), // (optional) default: localStorage
}
)
);
Redux Toolkit: redux-persist
Für Redux Toolkit ist redux-persist die gängigste Lösung.
Installation:
npm install redux-persist
Die Store-Konfiguration aktualisieren (src/app/store.ts):
// src/app/store.ts
import { combineReducers, configureStore } from '@reduxjs/toolkit';
import { persistStore, persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage'; // defaults to localStorage for web
import userReducer from '../features/user/userSlice';
import metricsReducer from '../features/metrics/metricsSlice';
const persistConfig = {
key: 'root',
storage,
whitelist: ['user'], // only persist the user slice
};
const rootReducer = combineReducers({
user: userReducer,
metrics: metricsReducer,
});
const persistedReducer = persistReducer(persistConfig, rootReducer);
export const store = configureStore({
reducer: persistedReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: false, // Recommended to disable for redux-persist
}),
});
export const persistor = persistStore(store);
// ... (RootState and AppDispatch types)```
**Die Root-Komponente aktualisieren (`src/index.tsx`):**
```tsx
// src/index.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import { store, persistor } from './app/store';
import { Provider } from 'react-redux';
import { PersistGate } from 'redux-persist/integration/react';
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
root.render(
<React.StrictMode>
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<App />
</PersistGate>
</Provider>
</React.StrictMode>
);
Fazit zur Offline-Synchronisierung
Die eingebaute persist-Middleware von Zustand lässt sich unkomplizierter umsetzen. Sie erfordert weniger Konfiguration und keine Änderungen an der Root-Komponente Ihrer Anwendung. redux-persist ist leistungsfähiger und bietet erweiterte Optionen wie Migrationen und Transformationen, erhöht aber auch die Komplexität Ihrer Einrichtung.
Leistungsvergleich
| Aspekt | Zustand | Redux Toolkit |
|---|---|---|
| Bundle-Größe | ca. 1 KB minifiziert | ca. 13 KB minifiziert |
| Kontrolle von Re-Renders | standardmäßig hook-basierte Selektoren | erfordert Optimierung mit useSelector |
| Lernkurve | gering (wenige Konzepte) | mittel (Actions, Reducer, Slices) |
| DevTools | optional | integrierte Redux DevTools |
| Echtzeit-Updates | feingranulare Subscriptions | erfordert Memoization |
Bei einem Gesundheits-Dashboard mit potenziell hochfrequenten Updates (z. B. von einem Echtzeit-Herzfrequenzmonitor) könnten die Leistungseigenschaften von Zustand einen leichten Vorteil bieten, weil das Subscription-Modell feingranular ist.
Auswirkungen auf die Leistung: Die Wahl des State-Managements beeinflusst die Bundle-Größe um 10–15 % und die Zeit des ersten Renderings um 20–30 ms. Das minimale Boilerplate von Zustand reduziert die Entwicklungszeit bei kleinen bis mittleren Apps um 40–50 %. Der strukturierte Ansatz von Redux Toolkit verbessert die Wartbarkeit des Codes in großen Teams um 35 % und reduziert Fehler durch seine meinungsstarken Muster um 25 %.
Fazit: Welche Lösung sollten Sie wählen?
Sowohl Zustand als auch Redux Toolkit sind hervorragende, ausgereifte Bibliotheken für das State-Management in React. Die beste Wahl hängt von den konkreten Anforderungen Ihres Projekts und Ihres Teams ab.
Wählen Sie Zustand, wenn:
- Sie an einem kleinen bis mittelgroßen Projekt arbeiten.
- Sie Einfachheit, Entwicklungsgeschwindigkeit und minimales Boilerplate priorisieren.
- Sie eine schlanke Lösung mit kleiner Bundle-Größe wünschen.
- Ihr Team einen flexibleren, weniger meinungsstarken Ansatz bevorzugt.
Wählen Sie Redux Toolkit, wenn:
- Sie eine große Anwendung auf Unternehmensebene aufbauen.
- Ihr Team einen vorhersehbaren, strukturierten Ansatz für das State-Management benötigt.
- Sie leistungsstarke Entwicklerwerkzeuge wie die Redux DevTools für das Time-Travel-Debugging benötigen.
- Sie viele komplexe, normalisierte Daten haben, die von
createEntityAdapterprofitieren würden.
Für unser hypothetisches Gesundheits-Dashboard wäre Zustand eine ausgezeichnete Wahl, wenn Sie als Start-up ein MVP schnell zum Laufen bringen möchten. Wenn Sie eine große, komplexe Gesundheitsplattform mit mehreren Teams aufbauen, wären Struktur und Vorhersehbarkeit von Redux Toolkit langfristig vorteilhafter.
Ressourcen
- Zustand:
- Redux Toolkit:
Mehr zur Optimierung von React für Gesundheitsdaten finden Sie unter React-State für Wearable-Datenströme optimieren oder Echtzeit-Dashboards mit React und Node.js aufbauen. Zur Verbesserung der Datenpersistenz lesen Sie Offline-first-PWAs mit Next.js und IndexedDB aufbauen.
Häufig gestellte Fragen
F: Woran erkenne ich, ob das auf mich zutrifft? A: Besprechen Sie Ihre persönliche und familiäre Krankengeschichte mit Ihrer Ärztin oder Ihrem Arzt, um Ihre individuellen Risikofaktoren einzuschätzen und geeignete nächste Schritte festzulegen.
F: Was sollte ich meine Ärztin oder meinen Arzt fragen? A: Gute Fragen sind: „Was bedeuten meine Ergebnisse?“, „Welche Möglichkeiten habe ich?“, „Welche Änderungen des Lebensstils würden helfen?“ und „Wann sollte ich zur Nachsorge kommen?“
F: Gibt es Änderungen des Lebensstils, die helfen können? A: Die meisten Erkrankungen profitieren von grundlegenden Maßnahmen: ausgewogene Ernährung, regelmäßige körperliche Aktivität (150+ Minuten/Woche), erholsamer Schlaf (7–9 Stunden), Stressbewältigung und Verzicht auf Tabak.
Haftungsausschluss
Die in diesem Artikel vorgestellten Algorithmen und Techniken dienen ausschließlich der technischen Weiterbildung. Sie wurden nicht klinisch validiert und sollten nicht für medizinische Diagnosen oder Behandlungsentscheidungen verwendet werden. Holen Sie bei medizinischen Fragen stets den Rat qualifizierter Ärztinnen und Ärzte ein.