Using Redux with React

Welcome to the tutorial on Using Redux with React. Think of Redux as a central library of information (state), and React components as library patrons who need to read or update information. This guide walks you through how Redux and React communicate to manage state efficiently and predictably.

Integrating Redux into a React Application

To connect Redux to React, follow these general steps:

React-Redux Provider

The Provider component makes the Redux store available to all nested components. It's like setting up a speaker system at a concert - once the Provider is in place, everyone (components) can hear (access the store).

import { Provider } from 'react-redux';
import configureStore from './store';
import ReactDOM from 'react-dom/client';
import App from './App';

const store = configureStore();

ReactDOM.createRoot(document.getElementById('root')).render(
  
    
      
    
  
);

By wrapping <App /> in <Provider />, all components gain access to the Redux store via context. This eliminates the need for prop-drilling.

useSelector Hook

To access Redux state in a component, use the useSelector hook from react-redux. This hook subscribes your component to the store and triggers re-renders on state updates.

import { useSelector } from 'react-redux';

function FruitsList() {
  const fruits = useSelector((state) => state.fruitState);

  return (
    <ul>
      {fruits.map((fruit) => (
        <li key={fruit.id}>{fruit.name}</li>
      ))}
    </ul>
  );
}

Analogy: useSelector is like a library card that lets you read specific books (parts of the state). You choose which book (slice of state) to read with the selector function.

Reusable Selector Functions

To reuse logic, define selectors separately:

export const selectFruits = (state) => state.fruitState;

import { useSelector } from 'react-redux';
import { selectFruits } from '../store/fruitReducer';

function FruitsList() {
  const fruits = useSelector(selectFruits);

  return (
    <ul>
      {fruits.map((fruit) => (
        <li key={fruit.id}>{fruit.name}</li>
      ))}
    </ul>
  );
}

useDispatch Hook

To update the Redux store, use the useDispatch hook, which provides the dispatch function.

import { useDispatch } from 'react-redux';
import { addFruit } from '../store/fruitReducer';

function AddMelonButton() {
  const dispatch = useDispatch();

  return (
    <button onClick={() => dispatch(addFruit({ id: 5, name: 'melon' }))}>
      Melon
    </button>
  );
}

Analogy: dispatch is like submitting a form - you send instructions (actions) to the store to update the data.

Dispatching Actions in useEffect

Sometimes you want to dispatch actions when the component mounts. Use useEffect for this:

import { useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { populateFruits } from '../store/fruitReducer';

function FruitsList() {
  const dispatch = useDispatch();
  const fruits = useSelector((state) => state.fruitState);

  useEffect(() => {
    dispatch(populateFruits());
  }, [dispatch]);

  return (
    <ul>
      {fruits.map((fruit) => (
        <li key={fruit.id}>{fruit.name}</li>
      ))}
    </ul>
  );
}

Technically, dispatch doesn't change, so adding it to the dependency array is safe but often unnecessary.

Follow-Along Exercise

  1. Install redux and react-redux in your React project.
  2. Define actions and reducers for fruits.
  3. Create the Redux store and wrap your app in Provider.
  4. Use useSelector to read fruits, and useDispatch to add fruits.

Real-World Example

In a messaging app:

Why Redux with React?

Further Exploration

Summary

You learned how to:

Resources

Learn more at the official React-Redux documentation: React-Redux Documentation