react-redux is the official binding library that connects a Redux store to your React components. This lesson covers useSelector for reading store state and useDispatch for sending actions, plus the Provider component that wires the store into your component tree.
1The Bridge
A React app and a Redux store don't know about each other out of the box ā they're two separate systems. The official react-redux library is the bridge that connects them, providing components and hooks that let React components read from and write to the Redux store.
Without react-redux, you'd have to manually subscribe every component to store updates yourself; the library's hooks (useSelector and useDispatch) handle that wiring for you.
// Example
console.log("Running React...");React š¤ Redux
Making the connection.
2The Provider
Before any component can access Redux, you must wrap your entire application in a <Provider> component imported from react-redux, passing your created store to it as the store prop: <Provider store={store}><App /></Provider>.
The Provider uses React's Context API under the hood to make that store available to every component in the tree, no matter how deeply nested, without having to manually pass it down as a prop at every level.
import { useSelector } from 'react-redux';
const count = useSelector((state) => state.counter.value);The Provider
Broadcasting the Store.
3Reading Data
Once the Provider is set up, any component can read data out of the store using the useSelector hook: const count = useSelector((state) => state.counter.value). You pass it a function, and useSelector returns exactly the piece of state that function extracts.
This lets a component pull only the specific slice of global state it actually needs, rather than receiving the entire state tree.
const user = useSelector(state => state.auth.user);Reading State
Extracting the Data.
4Selector Functions
The function passed into useSelector is called a selector. Redux calls it with the entire state object as its single argument, and the selector's job is simply to return whatever nested property you actually want, e.g. (state) => state.auth.token.
Because the selector receives the full state tree, you can drill down through as many nested levels as needed to reach the exact value your component cares about.
import { useDispatch } from 'react-redux';
const dispatch = useDispatch();Selectors
Picking specific data.
5Automatic Subscriptions
The real power of useSelector is that it automatically subscribes the calling component to the store ā you don't have to set up or tear down any subscription manually. Whenever an action is dispatched and the specific slice of state your selector returns actually changes, the component re-renders with the fresh value.
If the selected value doesn't change, useSelector skips the re-render, which is what keeps this subscription efficient rather than triggering updates on every single dispatch.
const handleIncrement = () => {
dispatch({ type: 'INCREMENT' });
};
<button onClick={handleIncrement}>+</button>Reactivity
Automatic UI Updates.
6Performance Optimization
Because useSelector re-renders a component whenever its returned value changes, the selector should be as specific as possible. Selecting the entire state object, like useSelector(s => s), means the component re-renders on every single dispatched action anywhere in the app, since the whole state reference changes each time.
Selecting a narrow, specific value instead, like useSelector(s => s.user.name), means the component only re-renders when that particular piece of data actually changes ā a critical difference for performance in larger applications.
<h1>Redux Hook Master Unlocked!</h1>Optimization
Select exactly what you need.
7Step-by-Step Breakdown
The Bridge. You have a React app. You have a Redux store. But they don't know about each other! To bridge the gap, we use an official library called react-redux. It provides special components and hooks to connect the two.
The Provider. Before any component can use Redux, you MUST wrap your entire application in a <Provider> component from react-redux. You pass your created Redux store to this Provider as a prop.
What prop MUST you pass to the <Provider> component to connect React to your Redux state?
- āstate
- āstore
Reading Data. Once the Provider is setup, any component can read data from the store. In modern functional components, we use the useSelector hook. It allows you to extract exactly the piece of state you need.
Selector Functions. The function you pass to useSelector is called a 'selector'. It receives the ENTIRE Redux state object as an argument, and you simply return the specific nested property you want.
Which react-redux hook is used to READ data from the global Redux store?
- āuseSelector
- āuseDispatch
Automatic Subscriptions. The magic of useSelector is that it automatically subscribes to the Redux store! If an action is dispatched and the specific data you selected changes, your component instantly re-renders with the new value.
Performance Optimization. Because useSelector triggers a re-render when its data changes, you should be SPECIFIC. Don't select the whole state object! If you select state, your component will re-render anytime ANYTHING in the app changes.
Triggering Updates. So we can read data. How do we UPDATE it? We need to dispatch actions. To do this, we use the useDispatch hook. It returns the dispatch function from our Redux store.
Dispatching Actions. Once you have the dispatch function, you can call it inside event handlers (like a button click) and pass it an Action object. This sends the action to the store, which updates the state, which triggers useSelector to update the UI!
Which hook returns the function you need to SEND actions to the Redux store?
- āuseSelector
- āuseDispatch
Action Creators. Instead of writing raw action objects manually every time, we usually import 'Action Creator' functions. These functions return the properly formatted action object for us.
The Full Cycle. Let's review the complete Redux cycle in a component: 1) Read data with useSelector. 2) Render the UI. 3) User clicks a button. 4) Use useDispatch to send an action. 5) Redux updates. 6) useSelector auto-refreshes the UI!
If you dispatch an action that changes a piece of state, do you need to manually tell useSelector to re-fetch the new data?
- āYes, you must call forceUpdate()
- āNo, useSelector handles it automatically
Hooks Master Unlocked. Incredible! You've mastered the bridge between React and Redux. You know how to extract data securely, optimize rendering performance, and trigger state updates globally. You're now ready to build massive, scalable applications!
Level Up š
Advanced cheat sheets, SEO tricks, and interview prep for this topic.
Browser Support
Fully supported.
Fully supported.
Fully supported.
Fully supported.
Accessibility (A11y)
1Loading and Error States Still Need Accessible Feedback
Data pulled in from `useSelector` often arrives asynchronously (after a fetch resolves into the store) ā make sure the component announces loading and error states with proper ARIA live regions rather than leaving screen reader users staring at a silent, empty UI.
2Dispatch-Triggered UI Changes Should Preserve Focus
When a `dispatch` call causes a modal to close or a list item to be removed, move focus to a sensible element afterward instead of letting it fall back to the document body, which disorients keyboard and screen reader users.
SEO Implications
- 1
Store-Derived Content Isn't Present Until Hydration
Content rendered from `useSelector` reflects whatever the store's initial state is during server rendering ā if the real data only arrives via a dispatched async action after mount, crawlers evaluating the initial HTML may see empty or placeholder content.
- 2
Pre-Populating the Store Server-Side Helps Indexing
For content that matters for SEO, hydrate the Redux store with real data before the initial render (e.g., via server-side data fetching) rather than relying on a client-only dispatch to populate it after the page loads.
Best Practices
Keep Selectors Narrow and Specific
Select the smallest piece of state a component actually needs, like `state.user.name`, rather than a broad object ā this limits re-renders to only the updates that actually matter to that component.
Use Action Creators Instead of Raw Action Objects
Import action creator functions (e.g., from a slice) rather than hand-writing `{ type: '...', payload: ... }` objects at every call site ā it reduces typos and keeps the action shape consistent across the app.
Frequent Bugs
A component re-renders far more often than expected after adding Redux.
The selector is returning a new object or array reference on every call, such as `useSelector(s => ({ ...s.user }))`, which `useSelector`'s reference equality check treats as a change every time. Select primitive values or use a memoized selector instead.
Calling a Redux hook throws an error saying it must be used within a Provider.
The component calling `useSelector` or `useDispatch` is rendered outside the `<Provider store={store}>` tree, or the Provider is missing entirely from the app's root file. Wrap the app's top-level component in `<Provider store={store}>`.
Real-World Examples
Shopping Cart Badge Driven by useSelector
A cart icon in the navbar reads only the item count from the store with `useSelector(state => state.cart.items.length)`, so it re-renders automatically whenever an item is added or removed anywhere in the app, without any manual event wiring.
function CartBadge() {
const itemCount = useSelector((state) => state.cart.items.length);
return <span className="badge">{itemCount}</span>;
}