Introduction to Redux
The Core Redux Concepts
Redux centers on three ideas: a single store holding all state, actions describing what happened (plain objects with a type), and reducers, pure functions that compute new state from the old state and an action. This one-way data flow makes state changes predictable and traceable.
Note: Actions are just data — they don't perform the change themselves, they only describe what should happen.
Warning: A reducer must be a pure function: no API calls, no random values, no mutating its arguments.
Example: The Core Redux Concepts
// Run in your local React project (npm install required)
import { createStore } from 'redux';
function counterReducer(state = { count: 0 }, action) {
if (action.type === 'increment') return { count: state.count + 1 };
return state;
}
const store = createStore(counterReducer);
store.dispatch({ type: 'increment' });
console.log(store.getState()); // count is now 1
⚠️ This example uses an npm package with no CDN build available here — run this in your local React project.
Connecting Redux to React
The react-redux package bridges Redux's plain-JavaScript store with React components. Wrapping your app in <Provider store={store}> makes the store available everywhere, and hooks like useSelector/useDispatch let components read state and dispatch actions.
Note: Provider goes once, near the very top of your component tree, just like BrowserRouter.
Warning: A component using useSelector or useDispatch must be rendered inside the Provider, or it will throw an error.
Example: Connecting Redux to React
// Run in your local React project (npm install required)
import { Provider } from 'react-redux';
import { store } from './store';
import App from './App';
ReactDOM.createRoot(document.getElementById('root')).render(
<Provider store={store}>
<App />
</Provider>
);
⚠️ This example uses an npm package with no CDN build available here — run this in your local React project.
When to Reach for Redux
Redux adds real setup overhead (store, reducers, actions), so it's most valuable for state that's complex, changes frequently, or needs to be shared across many unrelated parts of a large app. For simpler apps, Context API or component-local useState is often enough on its own.
Note: A good signal for needing Redux: many components across different parts of the app need to both read AND update the same piece of state.
Warning: Adding Redux to a small app 'just in case' usually adds more complexity than it removes — start simple and reach for it when you actually feel the pain.
Example: When to Reach for Redux
// Run in your local React project (npm install required)
// Simple local state: no Redux needed
function Counter() {
const [count, setCount] = React.useState(0);
return <button onClick={() => setCount(count + 1)}>{count}</button>;
}
// Complex, widely-shared state (auth, cart, notifications across the whole app):
// that's when Redux's centralized store starts to pay off.
- Mutating the state object directly inside a reducer instead of returning a new object.
- Putting all app state into Redux, even simple local UI state that a single component could manage with useState.
- Forgetting to wrap the app in <Provider store={store}>, so connected components can't access the store.
- Redux is a standalone state-management library, often used with React via react-redux.
- The store holds the entire app's state in one place, updated only through dispatched actions.
- Reducers are pure functions that take the current state and an action, returning new state.
- Not everything needs Redux — it shines for complex, widely-shared state, not simple local state.
Requires npm install redux react-redux — not available via CDN in this sandbox.
Chapter Quiz — Complete all 10 topics to unlock
0/10 topics done
Complete these topics first: