intermediate
Middleware
Intercept dispatch for async workflows, logging, analytics, side effects, and cross-cutting policies.
Middleware wraps dispatch: `store => next => action => {}`. It can log, delay, transform, or trigger async work before/after reducers run. The chain ends when `next(action)` reaches the reducer.
Common uses: redux-thunk (functions dispatched as async actions), custom analytics, auth token injection, crash reporting. RTK `configureStore` includes thunk by default.
const logger = (store) => (next) => (action) => {
console.log('dispatching', action);
const result = next(action);
console.log('next state', store.getState());
return result;
};
Prefer RTK Query or listener middleware for data fetching over hand-rolled thunk spaghetti. Keep middleware focused — not a second application layer.
The trade-off is cross-cutting async and logging in one pipeline versus harder-to-follow dispatch chains.
On interviews: where async belongs (thunk vs RTK Query vs component effect).
Common pitfalls: infinite dispatch loops, middleware ordering surprises, and business logic duplicated across many thunks.
Checklist:
- Middleware for cross-cutting dispatch concerns.
- Call next(action) unless swallowing intentionally.
- RTK Query for server cache lifecycle.
- Avoid heavy orchestration in middleware.