Claude Code Redux: State-Management in React mit KI beschleunigen

Redux war jahrelang das Synonym für zu viel Boilerplate für zu wenig Ergebnis. Action Types, Action Creators, Reducer-Switch-Statements, Store-Setup — allein die Grundstruktur eines einzelnen Features kostete Dutzende Zeilen Code, bevor überhaupt Logik hinzukam. Redux Toolkit (RTK) hat das verbessert. Claude Code macht es nochmals schneller: Slices generieren, Async-Thunks aufsetzen, RTK Query konfigurieren — in Minuten statt Stunden.

Dieser Artikel erklärt zunächst die Redux-Kernkonzepte, zeigt dann wie Redux Toolkit die Arbeit vereinfacht — und schließlich, wo Claude Code Redux-Workflows konkret beschleunigt.

Claude Code Mastery — Agents, Hooks, Workflows auf Deutsch

State-Management ist nur ein Anwendungsfall. Im Kurs lernst du, wie du Claude Code für komplette Entwicklungsabläufe, autonome Agents und professionelle Team-Workflows einsetzt. Einmalig bezahlt, kein Abo.

Zum Kurs — Jetzt starten → Einmalzahlung · Kein Abo · 14 Tage Rückgaberecht

1. Was ist Redux — Grundkonzepte

Redux ist ein State Container für JavaScript-Anwendungen. Die Kernidee: der gesamte Anwendungszustand liegt an einem einzigen Ort — dem Store. Das ist die Single Source of Truth. Kein State der halb in Component A, halb in Component B lebt, nirgends synchronisiert ist und bei jedem Re-Render frägst du dich, welche Version gerade gilt.

Der zweite Grundsatz: unidirektionaler Datenfluss. State ändert sich nicht direkt. Stattdessen wird eine Action dispatcht — ein einfaches Objekt das beschreibt, was passiert ist. Ein Reducer empfängt die alte State und die Action und gibt einen neuen State zurück. Der Store speichert diesen neuen State, React re-rendert was sich geändert hat.

Der Vorteil dieses Musters: der State-Verlauf ist vollständig nachvollziehbar. Jede Änderung wurde durch eine Action ausgelöst, jede Action ist im Redux DevTool sichtbar. Das macht Debugging vorhersagbar — statt im Component-Tree nach dem verlorenen State zu suchen, schaust du in den Action-Log.

Wann Redux verwenden? Redux lohnt sich, wenn State zwischen vielen nicht direkt verbundenen Components geteilt wird, wenn komplexe State-Transitions nachvollziehbar bleiben müssen, oder wenn das Team groß genug ist, dass konsistente State-Verwaltung wichtiger wird als Flexibilität. Für kleine Apps ist useState und useContext oft ausreichend.

2. Redux Toolkit: Modernes Redux ohne Boilerplate

Klassisches Redux erforderte für jedes Feature eine eigene Action-Types-Datei, Action-Creator-Funktionen, einen Reducer und die Store-Konfiguration. Redux Toolkit (RTK) bündelt das in deutlich weniger Code.

configureStore

Statt dem manuellen createStore mit mehreren Middleware-Konfigurationen:

import { configureStore } from '@reduxjs/toolkit';
import cartReducer from './features/cart/cartSlice';
import userReducer from './features/user/userSlice';

export const store = configureStore({
  reducer: {
    cart: cartReducer,
    user: userReducer,
  },
});

export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;

configureStore aktiviert automatisch Redux DevTools und die Thunk-Middleware. Das war früher Handarbeit.

createSlice

createSlice ist die wichtigste RTK-Funktion. Sie generiert automatisch Action Creators und Action Types aus den Reducer-Funktionen:

import { createSlice, PayloadAction } from '@reduxjs/toolkit';

interface CartState {
  items: CartItem[];
  total: number;
}

const initialState: CartState = {
  items: [],
  total: 0,
};

export const cartSlice = createSlice({
  name: 'cart',
  initialState,
  reducers: {
    addItem: (state, action: PayloadAction<CartItem>) => {
      state.items.push(action.payload);
      state.total += action.payload.price;
    },
    removeItem: (state, action: PayloadAction<string>) => {
      state.items = state.items.filter(item => item.id !== action.payload);
      state.total = state.items.reduce((sum, item) => sum + item.price, 0);
    },
    clearCart: (state) => {
      state.items = [];
      state.total = 0;
    },
  },
});

export const { addItem, removeItem, clearCart } = cartSlice.actions;
export default cartSlice.reducer;

Beachte: Die Reducer-Funktionen sehen aus, als würden sie den State direkt mutieren — state.items.push(...). Das funktioniert, weil RTK intern Immer.js verwendet, das die Mutationen abfängt und einen neuen immutablen State erzeugt. Man schreibt mutablen Code, bekommt immutablen State.

createAsyncThunk für asynchrone Operationen

Für API-Calls und andere asynchrone Operationen gibt es createAsyncThunk:

import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';

export const fetchUserProfile = createAsyncThunk(
  'user/fetchProfile',
  async (userId: string) => {
    const response = await fetch(`/api/users/${userId}`);
    if (!response.ok) throw new Error('Fetch fehlgeschlagen');
    return response.json();
  }
);

const userSlice = createSlice({
  name: 'user',
  initialState: { profile: null, loading: false, error: null },
  reducers: {},
  extraReducers: (builder) => {
    builder
      .addCase(fetchUserProfile.pending, (state) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(fetchUserProfile.fulfilled, (state, action) => {
        state.loading = false;
        state.profile = action.payload;
      })
      .addCase(fetchUserProfile.rejected, (state, action) => {
        state.loading = false;
        state.error = action.error.message ?? 'Unbekannter Fehler';
      });
  },
});

createAsyncThunk erzeugt automatisch drei Action Types: pending, fulfilled und rejected. Loading-States und Error-Handling werden damit standardisiert — kein eigenes Muster pro Feature mehr.

3. RTK Query: Data-Fetching ohne Boilerplate

RTK Query geht noch weiter. Es ist eine vollständige Data-Fetching- und Caching-Lösung, die direkt in Redux Toolkit eingebaut ist — ähnlich wie React Query, aber integriert mit dem Redux Store.

import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';

export const productsApi = createApi({
  reducerPath: 'productsApi',
  baseQuery: fetchBaseQuery({ baseUrl: '/api' }),
  tagTypes: ['Product'],
  endpoints: (builder) => ({
    getProducts: builder.query<Product[], void>({
      query: () => '/products',
      providesTags: ['Product'],
    }),
    getProductById: builder.query<Product, string>({
      query: (id) => `/products/${id}`,
      providesTags: (result, error, id) => [{ type: 'Product', id }],
    }),
    createProduct: builder.mutation<Product, Partial<Product>>({
      query: (body) => ({ url: '/products', method: 'POST', body }),
      invalidatesTags: ['Product'],
    }),
  }),
});

export const {
  useGetProductsQuery,
  useGetProductByIdQuery,
  useCreateProductMutation,
} = productsApi;

RTK Query generiert automatisch React-Hooks aus den Endpoints. useGetProductsQuery() gibt { data, isLoading, isError } zurück — inkl. automatischem Caching und Cache-Invalidierung über Tags.

4. React-Integration: Provider, useSelector, useDispatch

Der Store wird über den Provider der gesamten App zugänglich gemacht:

import { Provider } from 'react-redux';
import { store } from './store';

function App() {
  return (
    <Provider store={store}>
      <Router>
        <Routes />
      </Router>
    </Provider>
  );
}

In Components greift man dann über zwei Hooks auf den Store zu:

import { useSelector, useDispatch } from 'react-redux';
import { RootState, AppDispatch } from '../store';
import { addItem, removeItem } from '../features/cart/cartSlice';

function CartButton({ product }: { product: Product }) {
  const dispatch = useDispatch<AppDispatch>();
  const cartItems = useSelector((state: RootState) => state.cart.items);
  const isInCart = cartItems.some(item => item.id === product.id);

  return (
    <button onClick={() => dispatch(isInCart
      ? removeItem(product.id)
      : addItem(product)
    )}>
      {isInCart ? 'Entfernen' : 'In den Warenkorb'}
    </button>
  );
}

useSelector abonniert einen Teil des States — der Component re-rendert nur, wenn sich genau dieser Teil ändert. useDispatch gibt Zugriff auf die Dispatch-Funktion. Keine Class-Components, keine connect()-HOC mehr.

5. Claude Code Redux: Wo KI konkret hilft

Redux mit RTK ist deutlich angenehmer als klassisches Redux — aber es bleibt repetitiv. Jeder neue Feature-Bereich braucht ein Slice, eventuell Async-Thunks, TypeScript-Typen, Tests. Das ist Arbeit, die einem klar vorgegebenen Muster folgt. Genau dort greift Claude Code Redux.

Slices generieren lassen

claude "Erstelle ein RTK-Slice für einen Warenkorb. TypeScript.
State: items (CartItem[]), total (number), isOpen (boolean).
Actions: addItem, removeItem, updateQuantity, clearCart, toggleCart.
Separate types.ts-Datei für CartItem."

Claude Code liest die bestehenden Slice-Dateien im Projekt, erkennt die verwendeten Konventionen (Dateistruktur, Namensgebung, TypeScript-Stil) und generiert ein konsistentes Slice — kein Copy-Paste-Muster das man anpassen muss, sondern ein Ergebnis das direkt in den bestehenden Code passt.

Async-Thunks aufsetzen

claude "Füge zu userSlice.ts einen createAsyncThunk hinzu der
/api/users/:id aufruft. Fehlerbehandlung mit error.message.
extraReducers für pending/fulfilled/rejected ergänzen."

Claude Code liest userSlice.ts, sieht die bestehende Struktur und ergänzt den Thunk korrekt — mit den richtigen TypeScript-Typen, der korrekten extraReducers-Syntax und einem konsistenten Error-Handling-Pattern.

Migration von klassischem Redux zu RTK

Das größte Anwendungsfeld: bestehende Redux-Codebases auf RTK migrieren. Action Types, Action Creators, Switch-Statement-Reducer — das alles manuell zu konvertieren ist fehleranfällig und zeitaufwändig.

claude "Konvertiere src/reducers/products.js von klassischem Redux
zu RTK createSlice. Behalte die gleiche State-Struktur und
alle bestehenden Actions."

Claude Code liest den alten Reducer, extrahiert alle Action Types und ihre Logik, und schreibt ein äquivalentes RTK Slice — mit Immer-Mutationen statt Spread-Operators, generierten Action Creators statt manueller Definitionen.

Tipp bei Migrationen: Bitte Claude Code explizit, die Tests nach der Migration zu prüfen und anzupassen. Alte Tests haben oft noch die alten Action-Type-Strings hartcodiert — nach der RTK-Migration sind diese automatisch generiert und können sich leicht unterscheiden.

RTK Query Endpoints generieren

claude "Erstelle eine RTK Query API für /api/orders.
Endpoints: getOrders (List), getOrderById, createOrder, updateOrderStatus.
Cache-Tags für automatische Invalidierung bei Mutations."

RTK Query hat eine eigene API-Logik mit Tags und Invalidierung, die man beim ersten Mal nachschlagen muss. Claude Code kennt das Muster und setzt es korrekt auf — inklusive der TypeScript-Generics für Request- und Response-Typen.

Zwei verwandte Artikel die dieses Thema ergänzen:


Claude Code Mastery — von Redux bis zum produktiven Agenten

State-Management ist ein Anwendungsfall. Im Kurs lernst du Agents, MCP-Server, Hooks, Multi-Agent-Workflows und mehr. Vollständig auf Deutsch, einmalig bezahlt.

Jetzt starten → Einmalzahlung · Kein Abo · 14 Tage Rückgaberecht

Kurs · Claude Code Mastery

Von Redux-Boilerplate zum produktiven AI-Agenten

State-Management. Debugging. Agents. MCP. Hooks. Alles auf Deutsch, einmalig bezahlt — kein Abo, keine Plattformabhängigkeit.

Jetzt einsteigen → Kursübersicht ansehen →

Einmalzahlung · Kein Abo · 14 Tage Rückgaberecht