Introduction to Redux
The Problem Redux Solves
Why local state and useContext fall short in large applications: scattered state, complex update logic, and difficult debugging.
The core idea of Redux: a single, centralised store as the source of truth.
When Redux is worth the overhead — and when it is overkill.
An overview of the Redux ecosystem: Redux core, React-Redux, and Redux Toolkit.
Start
Store, Actions, Reducers
The three fundamental Redux principles: single source of truth, state is read-only, and changes are made with pure functions.
Actions as plain objects with a type field — the intent to change state.
Reducers as pure functions: (state, action) => newState — never mutate, always return a new value.
The store: createStore, getState, dispatch, and subscribe.
A complete counter example built from scratch without any library abstractions.
Start
Redux Toolkit — The Modern Way
Why the Redux team created Redux Toolkit (RTK) to eliminate boilerplate.
configureStore: setting up the store with sensible defaults (Redux DevTools, Thunk middleware).
createSlice: defining state, reducers, and actions in one place — and how Immer enables safe mutations inside reducers.
createAction and createReducer as lower-level alternatives.
Migrating a hand-written Redux setup to Redux Toolkit.
Start
Connecting Redux to React
The React-Redux library: providing the store to the component tree with Provider.
Reading state in components with useSelector — writing efficient selectors and understanding re-render triggers.
Dispatching actions from components with useDispatch.
Replacing useContext + useReducer with Redux in a real component.
Start
Organising State
Splitting the Redux store into feature slices: one slice per domain (auth, cart, notifications).
The feature-folder pattern: co-locating slice, selectors, and thunks by feature.
Combining slices with the reducers field in configureStore.
Naming conventions, action type prefixes, and keeping slices focused and independent.
Start
Async Logic with createAsyncThunk
Why reducers must be synchronous and where async logic belongs.
Thunks as the standard middleware for async work: what a thunk is and how it intercepts dispatch.
createAsyncThunk: defining an async operation and automatically generating pending, fulfilled, and rejected action types.
Handling all three lifecycle states in a slice with extraReducers and the builder callback.
Error handling, loading flags, and the abort controller for cancellable requests.
Start
RTK Query: Data Fetching and Caching
The problem RTK Query solves: eliminating manual loading/error/data state for every API call.
Defining an API service with createApi: baseQuery, endpoints, and query vs mutation.
Using the auto-generated hooks: useGetXQuery and usePostXMutation in components.
Caching, cache invalidation with tags (providesTags / invalidatesTags), and automatic re-fetching.
When to use RTK Query vs createAsyncThunk — choosing the right tool.
Start
Selectors and Derived Data
Why raw state selectors cause unnecessary re-renders and duplicate logic.
Writing reusable selector functions and co-locating them with their slice.
Memoised selectors with createSelector (Reselect) — input selectors, result function, and cache behaviour.
Combining selectors to derive complex data without storing redundant state.
Start
Middleware
What middleware is in Redux: a composable extension point that wraps dispatch.
The middleware signature: store => next => action => { }.
Built-in middleware: redux-thunk (included by default in RTK).
Writing a custom middleware: a logger, an analytics tracker, and an error reporter.
The Redux DevTools Extension: time-travel debugging, action history, and state diffs.
Start
Testing Redux Logic
Unit testing reducers: pure functions are trivial to test — input state + action → expected output state.
Unit testing selectors with createSelector.
Testing thunks with a mock store using redux-mock-store.
Integration testing: rendering a connected component with a real store and asserting on the UI.
Testing RTK Query endpoints with msw (Mock Service Worker).
Start
Real-World Patterns and Best Practices
Normalising relational data with createEntityAdapter to avoid nested state and duplication.
Optimistic updates: updating the UI before the server confirms and rolling back on failure.
Pagination and infinite scroll patterns with RTK Query.
Performance: avoiding over-fetching with proper selector memoisation and component splitting.
A checklist for structuring a scalable Redux codebase on a team.
Start
Capstone: Full-Featured App with Redux
Building a complete application — a task manager or e-commerce cart — with Redux Toolkit and RTK Query.
Covers authentication state, protected routes, real API integration, optimistic updates, and error handling.
Redux DevTools walkthrough: inspecting the action log, replaying actions, and exporting state for bug reports.
When to consider alternatives: Zustand, Jotai, and React Query — and how Redux fits in the broader ecosystem.
Start
