Predictable State

Redux Toolkit

Redux Toolkit ist der moderne, offizielle Weg, Redux zu schreiben. Es eliminiert Boilerplate, enthält Immer für immutable Updates und liefert Devtools, middleware sowie RTK Query mit.

intermediate15 min readUpdated 15. Sept. 2026
counterSlice.js
js
// features/counter/counterSlice.js
import { 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 default counterSlice.reducer;
Basiert auf
Redux
Immutability
Immer, integriert
Store Setup
configureStore
Logik
createSlice
Async
createAsyncThunk, RTK Query
Devtools
Standardmäßig aktiviert

Warum es wichtig ist

Warum Redux immer noch seinen Platz verdient

Vorhersehbar durch Design

Zustandsänderungen erfolgen nur über Actions und pure Reducer, sodass jeder Übergang nachvollziehbar und testbar ist.

Time-Travel Devtools

Überprüfe jede Action, vergleiche den State und spiele den Verlauf erneut ab, was selbst schwer findbare Bugs reproduzierbar macht.

Batteries included

Immer, middleware, Devtools und ein Data-Fetching-Layer sind integriert, sodass deutlich weniger Setup-Code geschrieben werden muss.

Das Gesamtbild

Die drei Kernideen hinter Redux

Ein einziger Store, pure Reducer und dispatched Actions. Toolkit behält diese Ideen bei und entfernt den unnötigen Overhead.

Der Store

Single Source

Ein einziges Objekt hält den Anwendungszustand, erstellt mit configureStore.

Reducer

Pure Updates

Funktionen, die den aktuellen State und eine Action entgegennehmen und den nächsten State zurückgeben.

Actions

Events

Einfache Objekte, die beschreiben, was passiert ist; sie werden von Komponenten dispatched und in Reducern verarbeitet.

Redux Toolkit auf einen Blick

Der Kern von Toolkit

configureStore

Erstellt den Store mit sinnvollen Standardwerten und aktivierten Devtools.

createSlice

Generiert Actions und Reducer für ein Feature in einer einzigen Datei.

useSelector

Liest einen Teil des States und löst ein Re-Render nur aus, wenn sich dieser Teil ändert.

useDispatch

Sendet Actions von Komponenten aus, um den Store zu aktualisieren.

createAsyncThunk

Verarbeitet asynchrone Aufgaben mit den Zuständen pending, fulfilled und rejected.

RTK Query

Ein integrierter Data-Fetching- und Caching-Layer für Server-State.

Eine kurze Geschichte

Von Boilerplate zu 'Batteries Included'

  1. 2015

    Redux veröffentlicht

    Ein von Flux inspirierter, vorhersehbarer State-Container wird zum Standard-Tool für den State in React.

    15
  2. 2019

    Redux Toolkit

    Das offizielle Paket entfernt Boilerplate und fügt Immer, Devtools und Standard-middleware hinzu.

    19
  3. 2021

    RTK Query

    Ein Data-Fetching- und Caching-Layer wird dem Toolkit hinzugefügt.

    21
  4. 2022

    Empfohlener Standard

    Toolkit wird zum einzig empfohlenen Weg, Redux zu schreiben; Legacy-Patterns werden nicht mehr empfohlen.

    22
  5. Heute

    Reif und stabil

    Eine zuverlässige Wahl für große Anwendungen mit komplexem, gemeinsam genutztem Client-State.

    Heute

Der vollständige Leitfaden

Redux Toolkit: Alles was Sie wissen müssen

Was ist Redux Toolkit?

Redux ist ein vorhersagbarer State Container: Ein einziger Store hält den Zustand Ihrer Anwendung, und die einzige Möglichkeit, diesen zu ändern, besteht darin, eine Action zu dispatchen, die von einem Pure Reducer verarbeitet wird. Genau diese Einschränkung macht Redux so leistungsfähig – jede Zustandsänderung ist explizit, nachvollziehbar und testbar.

Jahrelang war Redux zudem für seinen hohen Boilerplate-Anteil bekannt. Redux Toolkit hat das behoben. Es ist heute der offizielle und empfohlene Weg, Redux zu schreiben, und bündelt configureStore, createSlice, Immer für immutable Updates, thunk middleware und DevTools in einem Paket. Sie erhalten die Architektur ohne den unnötigen Overhead.

Der Store und Slices

Ein Slice bündelt die Reducer-Logik und die Actions eines Features an einem Ort. configureStore führt diese Slices im Store zusammen.

// app/store.js
import { configureStore } from "@reduxjs/toolkit";
import counterReducer from "../features/counter/counterSlice";
import todosReducer from "../features/todos/todosSlice";

export const store = configureStore({
  reducer: {
    counter: counterReducer,
    todos: todosReducer,
  },
});
// main.jsx
import { Provider } from "react-redux";
import { store } from "./app/store";

<Provider store={store}>
  <App />
</Provider>;

createSlice generiert die Action Creator und den Reducer automatisch für dich, sodass du Action-Type-Konstanten nie händisch schreiben musst. Immer treibt die Reducer an, was bedeutet, dass du Code schreiben kannst, der wie eine Mutation aussieht, während der State unveränderlich (immutable) bleibt.

// features/todos/todosSlice.js
import { createSlice } from "@reduxjs/toolkit";

const todosSlice = createSlice({
  name: "todos",
  initialState: [],
  reducers: {
    add(state, action) {
      state.push(action.payload);
    },
    toggle(state, action) {
      const todo = state.find((t) => t.id === action.payload);
      if (todo) todo.done = !todo.done;
    },
    remove(state, action) {
      return state.filter((t) => t.id !== action.payload);
    },
  },
});

export const { add, toggle, remove } = todosSlice.actions;
export default todosSlice.reducer;

Lesen und Dispatching

Komponenten lesen den State mit useSelector und senden Actions mit useDispatch.

// TodoList.jsx
import { useSelector, useDispatch } from "react-redux";
import { add, toggle } from "../features/todos/todosSlice";

export function TodoList() {
  const todos = useSelector((state) => state.todos);
  const dispatch = useDispatch();

  return (
    <ul>
      {todos.map((todo) => (
        <li key={todo.id} onClick={() => dispatch(toggle(todo.id))}>
          {todo.done ? "✓" : "○"} {todo.text}
        </li>
      ))}
      <button onClick={() => dispatch(add({ id: 1, text: "New" }))}>
        Add
      </button>
    </ul>
  );
}

Wähle den kleinstmöglichen Slice aus, den du benötigst. useSelector rendert die Komponente neu, wenn sich der ausgewählte Wert ändert; das Auswählen des gesamten States würde diese Optimierung zunichtemachen. Nutze createSelector von Reselect, wenn ein abgeleiteter Wert ansonsten bei jedem Render-Vorgang neu berechnet werden müsste.

Asynchrone Logik mit Thunks

createAsyncThunk generiert die drei Action-Typen, die ein asynchroner Request erzeugt und die du in extraReducers behandelst.

// features/users/usersSlice.js
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";

export const fetchUsers = createAsyncThunk("users/fetch", async () => {
  const res = await fetch("/api/users");
  if (!res.ok) throw new Error("Failed to fetch users");
  return res.json();
});

const usersSlice = createSlice({
  name: "users",
  initialState: { items: [], status: "idle", error: null },
  reducers: {},
  extraReducers: (builder) => {
    builder
      .addCase(fetchUsers.pending, (state) => {
        state.status = "loading";
      })
      .addCase(fetchUsers.fulfilled, (state, action) => {
        state.status = "succeeded";
        state.items = action.payload;
      })
      .addCase(fetchUsers.rejected, (state, action) => {
        state.status = "failed";
        state.error = action.error.message;
      });
  },
});

Dies ist das explizite Redux-Pattern: Loading, Success und Failure sind alles Actions, die du in den Devtools inspizieren kannst.

RTK Query für den Server-State

Beim Datenabruf macht RTK Query Thunks komplett überflüssig. Du definierst einen API-Slice mit Endpunkten, und das Tool übernimmt das Caching, die Deduplizierung, die Invalidierung sowie das Refetching.

// features/api/apiSlice.js
import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";

export const api = createApi({
  reducerPath: "api",
  baseQuery: fetchBaseQuery({ baseUrl: "/api" }),
  tagTypes: ["Post"],
  endpoints: (builder) => ({
    getPosts: builder.query({ query: () => "posts", providesTags: ["Post"] }),
    addPost: builder.mutation({
      query: (body) => ({ url: "posts", method: "POST", body }),
      invalidatesTags: ["Post"],
    }),
  }),
});

export const { useGetPostsQuery, useAddPostMutation } = api;
// Posts.jsx
const { data, isLoading, error } = useGetPostsQuery();

RTK Query ist die Antwort von Redux auf TanStack Query: Der Server-State wird in einem Cache mit eigenem Lebenszyklus verwaltet, während der Client-State in Slices bleibt. Wenn diese beiden Verantwortlichkeiten an einem Ort vermischt werden, wird der Code in Redux-Apps oft unübersichtlich.

Middleware und DevTools

configureStore aktiviert die Redux DevTools Extension und enthält standardmäßig die Thunk-middleware. Sie können eigene middleware für Logging, Analytics oder Side Effects hinzufügen.

// middleware.js
const logger = (store) => (next) => (action) => {
  console.log("dispatching", action.type);
  return next(action);
};

export const store = configureStore({
  reducer: rootReducer,
  middleware: (getDefault) => getDefault().concat(logger),
});

Die DevTools ermöglichen es Ihnen, jede dispatched Action zu untersuchen, den State davor und danach zu vergleichen (Diff) und den Verlauf erneut abzuspielen – der wichtigste Grund, warum Teams Redux für komplexen State wählen.

Best Practices

  • Verwende Redux Toolkit und niemals handgeschriebenes Redux.
  • Erstelle pro Feature einen eigenen Slice und fasse zusammengehörige Logik zusammen.
  • Wähle in useSelector den kleinstmöglichen State-Slice aus.
  • Nutze createSelector für abgeleitete Daten, deren Berechnung rechenintensiv ist.
  • Verwalte Server-State in RTK Query, nicht in Slices.
  • Speichere nur serialisierbare Daten; halte nicht-serialisierbare Werte aus dem Store fern.
  • Modelliere Actions als Ereignisse, die bereits eingetreten sind, und nicht als Setter.

Häufige Fehler

  • Den gesamten State auszuwählen und bei jeder Änderung ein Re-Rendering auszulösen.
  • Serverdaten in Slices zu speichern und Lade-Flags manuell zu verwalten.
  • Nicht-serialisierbare Werte wie Klasseninstanzen oder Funktionen zu speichern.
  • Den State außerhalb eines Reducers zu mutieren.
  • Redux für lokalen Component-State zu verwenden, den useState besser handhaben würde.
  • Ausführliches Legacy Redux anstelle von Slices zu schreiben.

Wie geht es weiter?

Redux Toolkit ist die bewährte Wahl für große, komplexe Client-States. Vergleiche es mit der integrierten Context API von React sowie dem schlankeren Zustand und lagere Server-Belange in TanStack Query oder RTK Query aus. Für Vue wird diese Rolle von Pinia übernommen.

Einen Reducer schreiben

createSlice generiert Action-Creators und nutzt Immer, sodass du Code schreiben kannst, der wie eine Mutation aussieht, aber immutable bleibt.

Toolkit
const slice = createSlice({
  name: "todos",
  initialState: [],
  reducers: {
    add(state, action) {
      state.push(action.payload);
    },
  },
});
Legacy Redux
function todos(state = [], action) {
  switch (action.type) {
    case "todos/add":
      return [...state, action.payload];
    default:
      return state;
  }
}
// plus action creators,
// constants and types

State lesen

Wähle den kleinstmöglichen Slice aus, damit die Komponente nur re-rendert, wenn sich dieser spezifische Wert ändert.

Bevorzugt
const count = useSelector(
  (state) => state.counter.value,
);
Vermeiden
const state = useSelector(
  (state) => state,
);
// re-renders on any change

Häufig gestellte Fragen

Häufig gestellte Fragen

Keep learning

Related topics from the roadmap.

$ Lernen Sie jetzt

Bereit, Redux Toolkit zu lernen?

Unser interaktives Tutorial führt Sie Schritt für Schritt durch Redux Toolkit — mit Quizzen und echtem Code, den Sie im Browser ausführen können.