Three nouns carry the whole model, and they are worth learning outside React 7,897 . An action is a plain object with a required type string and, by convention, a payload; it describes an event that happened — 'cart/itemAdded' — not a command to a component. A reducer is a pure function (state, action) => nextState. A store holds one state value, runs the reducer for every dispatched action, and notifies subscribers afterwards.
import { configureStore } from '@reduxjs/toolkit';
const counter = (state = 0, action) => // a reducer: pure, synchronous
action.type === 'counter/incremented' ? state + 1
: action.type === 'counter/addedBy' ? state + action.payload
: state; // unknown action: hand back what you got
const store = configureStore({ reducer: counter });
const stop = store.subscribe(() => console.log('state is now', store.getState()));
store.dispatch({ type: 'counter/incremented' });
store.dispatch({ type: 'counter/addedBy', payload: 10 });
store.dispatch({ type: 'counter/unknown' }); // reducer returns state, subscribers still run
stop();state is now 1 state is now 11 state is now 11
Those three methods, plus replaceReducer(next) for code splitting, are the store's entire surface; slices, thunks, selectors and queries are conveniences built on them.
The unknown-action line matters more than it looks. Reducers see every action, so returning the old state is not politeness: leave that branch out and the first unrelated dispatch wipes the slice to undefined. The initial value arrives the same way — the store dispatches a setup action once, and the default parameter answers.