Redux là một store toàn cục với luồng dữ liệu một chiều (one-way data flow):
1. UI dispatch một action — plain object mô tả "chuyện gì vừa xảy ra": { type: 'cart/itemAdded', payload: item }.
2. Action đi qua middleware (nếu có) — nơi duy nhất được làm side effect: gọi API, log, tác vụ async (redux-thunk/saga). Middleware có thể chặn, biến đổi, hoặc dispatch thêm action.
3. Reducer nhận (state, action) và trả về state MỚI — hàm thuần: không mutate state cũ, không gọi API, không random; cùng input luôn cho cùng output.
4. Store thay state hiện tại bằng kết quả reducer và thông báo cho các subscriber.
5. UI đọc state qua selector (useSelector) — component chỉ re-render khi phần state nó chọn thay đổi.
// reducer: a pure function
function cartReducer(state = initialState, action) {
switch (action.type) {
case 'cart/itemAdded':
return { ...state, items: [...state.items, action.payload] }
default:
return state
}
}Vì sao thiết kế như vậy: state chỉ đổi qua action + reducer thuần → mọi thay đổi truy vết được (time-travel debugging trong Redux DevTools), side effect bị dồn về một tầng duy nhất.
Hiện nay nên viết qua Redux Toolkit: createSlice (dùng Immer nên viết như mutate mà kết quả vẫn immutable) + createAsyncThunk cho async.