Introduction
Redux is a predictable state container for JavaScript apps, commonly used with React for managing global application state. It centralizes state in a single 'store' and enforces that state can only be changed by dispatching 'action' objects that describe what happened, which are processed by pure 'reducer' functions that compute the next state. This unidirectional data flow makes state changes traceable, debuggable, and testable. Modern Redux development uses Redux Toolkit (RTK), the officially recommended approach, which drastically reduces boilerplate compared to classic hand-written Redux.
Cricket analogy: Redux is like a single official scorebook (store) that only gets updated when an official event report (action) like "four runs scored" is filed, processed by a strict scoring rulebook (reducer) — this makes every run traceable to a specific ball, and modern scoring apps (Redux Toolkit) cut the manual paperwork dramatically.
Syntax
// Redux Toolkit: creating a slice (state + reducers + actions in one place)
import { createSlice, configureStore } from '@reduxjs/toolkit';
const counterSlice = createSlice({
name: 'counter',
initialState: { value: 0 },
reducers: {
incremented: (state) => {
state.value += 1; // Immer lets us 'mutate' safely under the hood
},
decremented: (state) => {
state.value -= 1;
},
addedBy: (state, action) => {
state.value += action.payload;
},
},
});
export const { incremented, decremented, addedBy } = counterSlice.actions;
const store = configureStore({
reducer: { counter: counterSlice.reducer },
});
export default store;Explanation
The **store** holds the single source of truth for application state. **Actions** are plain objects with a type field (and usually a payload) describing what happened; createSlice auto-generates action creators like incremented() for you. **Reducers** are pure functions that take the current state and an action and return the next state; inside RTK's createSlice, you can write code that looks like direct mutation (state.value += 1) because RTK uses the Immer library internally to produce an immutable update safely. **Dispatch** is how components trigger state changes: calling dispatch(incremented()) sends the action through the store to the appropriate reducer, and the store notifies subscribed components so they re-render with the new state.
Cricket analogy: The scorebook (store) is the single source of truth; an event slip (action) like {type: "FOUR", payload: 4} is filed automatically by the scoring app (createSlice); the scoring rule (reducer) reads the current total and the slip and looks like it directly adds 4 to the total, even though internally it safely creates a new tally (Immer); filing the slip (dispatch) updates the scorebook and refreshes the stadium screen (notifies subscribers).
Example
// Connecting Redux to React with react-redux hooks
import { Provider, useSelector, useDispatch } from 'react-redux';
import store from './store';
import { incremented, decremented, addedBy } from './counterSlice';
function Counter() {
const count = useSelector((state) => state.counter.value);
const dispatch = useDispatch();
return (
<div>
<p>Count: {count}</p>
<button onClick={() => dispatch(incremented())}>+1</button>
<button onClick={() => dispatch(decremented())}>-1</button>
<button onClick={() => dispatch(addedBy(5))}>+5</button>
</div>
);
}
function App() {
return (
<Provider store={store}>
<Counter />
</Provider>
);
}Output
Wrapping the app in <Provider store={store}> makes the Redux store available to any nested component. useSelector reads state.counter.value and re-renders Counter only when that specific slice of state changes; useDispatch returns the store's dispatch function. Clicking '+5' dispatches addedBy(5), the addedBy reducer case adds 5 to state.value, and the displayed count updates accordingly.
Cricket analogy: Wrapping the whole broadcast in the central data feed (Provider) makes the scoreboard app (store) available everywhere; the run-tally widget reads only "state.batsman.runs" (useSelector) and updates only when that specific number changes; tapping "+4" dispatches an "addedRuns(4)" action, the scoring rule adds 4 to the tally, and the displayed score updates.
Key Takeaways
- Redux centralizes application state in a single store, updated only via dispatched action objects processed by pure reducers.
- Actions describe 'what happened' (type + optional payload); reducers describe 'how state changes' in response.
- Redux Toolkit (createSlice, configureStore) is the modern, recommended way to write Redux, eliminating most boilerplate and using Immer for safe 'mutable-looking' updates.
- react-redux's useSelector and useDispatch hooks connect React components to the Redux store.
- Redux is best suited for larger apps with complex, shared state and needs like time-travel debugging or middleware (e.g., logging, async thunks).
Practice what you learned
1. What are the three core building blocks of classic Redux?
2. In Redux Toolkit's createSlice, why can reducer code appear to directly mutate state (e.g., state.value += 1)?
3. What is the role of dispatch in Redux?
4. Which react-redux hook is used to read a piece of state from the Redux store inside a component?
5. What is the officially recommended way to write Redux logic today?
Was this page helpful?
You May Also Like
The useReducer Hook
Understand how useReducer manages complex component state using actions and a pure reducer function.
Context API for State Management
Learn how React's built-in Context API lets you share state across components without prop drilling.
State Management Patterns Comparison
Compare local state, Context API, and Redux/Zustand-style libraries to choose the right tool for each situation.
Related Reading
Related Study Notes in Web Development
Browse all study notesWebSockets Study Notes
Web Development · 30 topics
Web DevelopmentWebAssembly Study Notes
WebAssembly · 30 topics
Web DevelopmentgRPC Study Notes
Protocol Buffers · 30 topics
Web DevelopmentSpring Boot Study Notes
Java · 30 topics
Web DevelopmentFlask Study Notes
Python · 30 topics
Web DevelopmentDjango Study Notes
Python · 30 topics