Article image State Management with Redux

30. State Management with Redux

Page 74 | Listen in audio

State management is a critical aspect of any modern web application, especially when using a library like React. As applications grow in complexity, managing state across components can become challenging. This is where Redux comes into play. Redux is a predictable state container for JavaScript apps, commonly used with React for managing the state of an application. It helps in maintaining a consistent state across the app, making debugging and testing easier.

Redux is based on a few key principles:

  • Single Source of Truth: The state of your whole application is stored in an object tree within a single store. This means that rather than having state scattered across many components, you have one centralized place for all your application state.
  • State is Read-Only: The only way to change the state is to emit an action, an object describing what happened. This ensures that state transitions are predictable and traceable.
  • Changes are Made with Pure Functions: To specify how the state tree is transformed by actions, you write pure reducers. A reducer is a function that takes the previous state and an action, and returns the next state.

To effectively use Redux in a React application, you need to understand a few core concepts: the store, actions, and reducers.

The Store

The store is the object that brings actions and reducers together. There is a single store in a Redux application. The store has the following responsibilities:

  • Holds application state.
  • Allows access to state via getState().
  • Allows state to be updated via dispatch(action).
  • Registers listeners via subscribe(listener).
  • Handles unregistering of listeners via the function returned by subscribe(listener).

To create a store, you use the createStore function from Redux:

import { createStore } from 'redux';
import rootReducer from './reducers';

const store = createStore(rootReducer);

The rootReducer is a combination of all the reducers in your application, which are combined using Redux's combineReducers function.

Actions

Actions are payloads of information that send data from your application to your Redux store. They are the only source of information for the store. You send them to the store using store.dispatch().

An action is a plain JavaScript object that must have a type property. Here is a basic example of an action:

const incrementAction = {
  type: 'INCREMENT',
  payload: 1
};

The action type is usually a string constant. It's a good practice to define action types as constants to avoid typos and have a single source of truth for action types.

Reducers

Reducers specify how the application's state changes in response to actions sent to the store. Remember that actions only describe what happened, but don't describe how the application's state changes.

A reducer is a pure function that takes the previous state and an action, and returns the next state:

function counter(state = 0, action) {
  switch (action.type) {
    case 'INCREMENT':
      return state + action.payload;
    case 'DECREMENT':
      return state - action.payload;
    default:
      return state;
  }
}

In this example, the counter reducer handles two types of actions: INCREMENT and DECREMENT. Depending on the action type, it adjusts the state accordingly.

Connecting Redux to React

To connect Redux to a React application, you typically use the react-redux library. This library provides a set of tools to connect your React components to the Redux store. The two most important tools are the Provider component and the connect function.

The Provider component makes the Redux store available to any nested components that need to access the Redux store:

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

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);

The connect function connects a React component to the Redux store. It can be used to map state and dispatch to the props of your component:

import { connect } from 'react-redux';

const mapStateToProps = state => ({
  count: state.counter
});

const mapDispatchToProps = dispatch => ({
  increment: () => dispatch({ type: 'INCREMENT', payload: 1 }),
  decrement: () => dispatch({ type: 'DECREMENT', payload: 1 })
});

export default connect(mapStateToProps, mapDispatchToProps)(CounterComponent);

In this example, mapStateToProps is a function that extracts the necessary state from the Redux store and maps it to the props of the component. mapDispatchToProps is a function that creates functions which dispatch actions to the store, and these functions are also mapped to the component's props.

Middleware

Middleware provides a third-party extension point between dispatching an action, and the moment it reaches the reducer. They are used for logging, crash reporting, performing asynchronous tasks, etc.

Redux Thunk is a popular middleware for handling asynchronous actions in Redux. It allows you to write action creators that return a function instead of an action. The thunk can be used to delay the dispatch of an action, or to dispatch only if a certain condition is met.

import thunk from 'redux-thunk';
import { createStore, applyMiddleware } from 'redux';

const store = createStore(rootReducer, applyMiddleware(thunk));

With Redux Thunk, you can write an action creator like this:

function fetchUser(id) {
  return function(dispatch) {
    dispatch({ type: 'FETCH_USER_REQUEST' });
    return fetch(`/api/user/${id}`)
      .then(response => response.json())
      .then(json => dispatch({ type: 'FETCH_USER_SUCCESS', payload: json }))
      .catch(error => dispatch({ type: 'FETCH_USER_FAILURE', error }));
  };
}

Redux is a powerful tool for managing state in a React application, but it also comes with a learning curve. Understanding the core concepts of Redux — store, actions, reducers, and middleware — is essential to harness its full potential. With Redux, you gain a predictable state management solution that scales well as your application grows in complexity.

Now answer the exercise about the content:

What is the main purpose of using Redux in a React application?

You are right! Congratulations, now go to the next page

You missed! Try again.

Article image Redux Toolkit: Simplifying Redux Workflow

Next page of the Free Ebook:

75Redux Toolkit: Simplifying Redux Workflow

9 minutes

Earn your Certificate for this Course for Free! by downloading the Cursa app and reading the ebook there. Available on Google Play or App Store!

Get it on Google Play Get it on App Store

+ 6.5 million
students

Free and Valid
Certificate with QR Code

48 thousand free
exercises

4.8/5 rating in
app stores

Free courses in
video, audio and text