foundation
Actions
Model events as serializable descriptions of what happened rather than direct mutation commands.
Actions are plain objects describing what happened: `{ type: 'todos/toggle', payload: id }`. They are the public write API — serializable, loggable, replayable. Redux Toolkit `createSlice` generates action creators automatically.
// RTK slice action
const todosSlice = createSlice({
name: 'todos',
initialState: [],
reducers: {
toggled(state, action) {
const todo = state.find((t) => t.id === action.payload);
if (todo) todo.done = !todo.done;
},
},
});
// dispatch(todosSlice.actions.toggled('t1'))
Action types should be namespaced (`feature/event`) to avoid collisions. Async workflows dispatch multiple actions: pending, fulfilled, rejected — or delegate to RTK Query endpoints.
The trade-off is explicit event history and debuggability versus ceremony for simple local updates.
On interviews: why actions are events, not imperative "setState" calls with hidden side effects.
Common pitfalls: non-serializable payloads (functions, promises), stringly-typed types without constants, and fat actions that carry entire server responses when normalization belongs in reducers.
Checklist:
- Serializable type + payload.
- Namespaced action types.
- createAction/createSlice for ergonomics.
- Separate intent (action) from transition (reducer).