05th Jun 2023

How to use Redux in ReactJS

Build React Application

What is Redux

React Redux is a popular library that combines React, a JavaScript library for building user interfaces, with Redux, a predictable state container for managing application state. It is commonly used in large-scale React applications to manage the state of the application and make it easier to maintain and update.

React Redux follows the principles of a unidirectional data flow, where the state is stored in a single source called the Redux store. Components can subscribe to the store and access the state as props. When the state changes, React Redux ensures that the components affected by the change are re-rendered efficiently.

When to use Redux

  • Large-scale applications: Redux is particularly useful when you have a complex application with a significant amount of state that needs to be shared across multiple components. It helps in maintaining a centralized state management system.
  • Shared state: If you have components that need to share state or data, Redux provides a convenient way to manage and access that shared state. It eliminates the need to pass props through multiple levels of components
  • Complex data flow: Redux simplifies the management of data flow in your application. If you have a complex data flow, with frequent updates and interdependencies between components, Redux can provide a clear and structured way to handle this flow.
  • Time-travel debugging: Redux offers a powerful feature called time-travel debugging. It allows you to record and replay state changes, making it easier to debug and reproduce issues in your application.
  • Server-side rendering: If you are using server-side rendering in your React application, Redux can help in managing the initial state of your application on the server and synchronize it with the client-side state.

Redux is used to keep and update data for numerous components to share throughout your applications, all while remaining independent of the components.

Redux with React

Redux is a standalone library that can be used with numerous JavaScript frameworks, including Angular, Inferno, Vue, Preact, React, and many more, as we previously discussed.

The reason why we use Redux with React is because the idea of states and lifecycles was incorporated into the architecture of React. Additionally, state cannot be changed directly in React; instead, the function setState must be used. Because they share the same idea and behaviour of a state object, Redux concepts are easy to apply as a result.

Now let's start on how to implement Redux in React.

Implement Redux in React

First, we need to install react redux library, following below comment:

                                
                                     
 Npm install react-redux
 Npm install redux
                                
                            

We need to learn redux, actions, reducers, the store, and dispatch are key concepts that work together to manage the state of your application.

Actions
  • Actions are plain JavaScript objects that represent an intention to change the state of your application.
  • They must have a type property, which is a string that describes the type of action being performed.
  • Additional data or payload can be included in the action object to provide more information to the reducers.
  • Actions are typically defined as functions called action creators, which return the action object.
Reducers
  • Reducers are pure functions responsible for specifying how the state should change in response to actions.
  • They take the current state and an action as arguments and return a new state based on the action type.
  • Reducers should not modify the original state but create a new state object with the necessary updates.
  • It's common to have multiple reducers that manage different parts of the state, which are combined into a single root reducer using the combineReducers function.
Store
  • The store is a JavaScript object that holds the application state.
  • It is created using the createStore function from Redux, which takes the root reducer as an argument.
  • The store provides methods like getState(), dispatch(action), and subscribe(listener) to interact with the state and receive updates.
  • The store is the single source of truth for your application's state and manages the flow of actions and state updates.
Dispatch
  • Dispatching is the process of sending an action to the Redux store.
  • The dispatch function is provided by the Redux store and is used to trigger a state change.
  • When an action is dispatched, it flows through the reducers, and the store's state is updated accordingly.
  • Components can dispatch actions to update the state, typically in response to user interactions or asynchronous operations.
  • Dispatching an action is done by calling store.dispatch(action).
Provider

In Redux with React, the Provider component is a higher-order component (HOC) provided by the React Redux library. It is used to make the Redux store available to all components in your application without passing it explicitly through props. The Provider component is typically placed at the root of your React component tree and wraps the top-level component of your application. Here's an example of how to use the Provider component:

The syntax for Provider is as follows

                                
                                      
  import { Provider } from "react-redux";
  <Provider store={store}>
  <Home></Home>
  </Provider>
                                
                            
CreateStore

The createStore function is a core function provided by Redux, a JavaScript library for managing application state. It is used to create a Redux store, which serves as a single source of truth for the state of your application.

The syntax for creating a store using createStore is as follows:

                                
                                    
  import {createStore } from "redux";
  const store = createStore(reducer);
                                
                            

A reducer is a pure function that specifies how the state should change in response to actions. It takes the current state and an action as arguments and returns a new state.

The dispatch function is a method provided by the Redux store. It is used to send actions to the store, which in turn triggers the state update process. Dispatching an action is the primary way to modify the state in a Redux application.

Dispatch

The dispatch function is a method provided by the Redux store. It is used to send actions to the store, which in turn triggers the state update process. Dispatching an action is the primary way to modify the state in a Redux application.

The syntax to dispatch an action is as follows:

                                
                                     
  function counterReducer(state = { value: 0 }, action) {
    switch (action.type) {
      case "counter/incremented":
        return { value: state.value + 1 };
      case "counter/decremented":
        return { value: state.value - 1 };
      default:
        return state;
    }
  }
 let store = createStore(counterReducer);
 store.dispatch({ type: "counter/incremented" });
                                
                            
Subscribe

The subscribe method is a function provided by the Redux store that allows components or other parts of your application to listen to changes in the state. It enables you to respond to state updates and take appropriate actions when the state changes.

The syntax for subscribing to the store is as follows:

                                
                                     
  const unsubscribe = store.subscribe(() => {
  const currentState = store.getState();
  console.log('Current state:', currentState);
 });
                                
                            

when using React with Redux, subscribing to the store directly is not typically necessary. Instead, React Redux's connect function and the component's rendering process handle the updates automatically based on the state changes. The subscribe method is more commonly used in non-React environments or for specific advanced use cases.

Connect

In React Redux, the connect function is a key utility provided by the React Redux library. It allows you to connect your React components to the Redux store, enabling them to access the state from the store and dispatch actions.

The connect function is used to create a higher-order component (HOC) that wraps your component, enhancing it with Redux functionality.

Here's the basic syntax of connect:

                                
                                    
  import { connect } from 'react-redux';
  import { incrementCount } from './actions';
  const MyComponent = ({ count, increment }) => {
    return (
      <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
      </div>
    );
  };
  const mapStateToProps = (state) => {
    return {
      count: state.count,
    };
  };
  const mapDispatchToProps = {
    increment: incrementCount,
  };
  export default connect(mapStateToProps, mapDispatchToProps)(MyComponent);
                                
                            
  • mapStateToProps (optional): A function that maps the state from the Redux store to the props of your component. It receives the state as an argument and returns an object that defines the props to be passed to the wrapped component.
  • mapDispatchToProps (optional): A function or an object that maps action creators or plain actions to props. It allows your component to dispatch actions to update the state. If mapDispatchToProps is not specified, dispatch is automatically injected as a prop.
  • Component: The React component you want to connect to the Redux store.

MyComponent is connected to the Redux store using connect. It maps the count state from the store to the count prop of the component using mapStateToProps. It also maps the incrementCount action creator to the increment prop of the component using mapDispatchToProps.

Now, MyComponent can access the count prop, which is derived from the Redux store, and dispatch the incrementCount action by calling increment. When the action is dispatched, Redux updates the state, and the component will receive the updated props.

ApplyMiddleware

In React Redux, the applyMiddleware function is a utility provided by the Redux library that allows you to apply middleware to the Redux store. Middleware in Redux is a way to enhance the store's dispatch function with additional functionality.

The applyMiddleware function is typically used when creating the Redux store to enable the use of middleware. Here's an example of how to use applyMiddleware:

                                
                                    
  import { applyMiddleware } from "redux";
  import thunk from "redux-thunk";
  function counterReducer(state = { value: 0 }, action) {
      switch (action.type) {
        case "counter/incremented":
          return { value: state.value + 1 };
        case "counter/decremented":
          return { value: state.value - 1 };
        default:
          return state;
      }
  }
  let store = createStore(counterReducer, applyMiddleware(thunk));
                                
                            

Middleware functions sit between the dispatching of an action and the moment it reaches the reducers, allowing you to intercept, modify, or handle actions before they reach the reducers. Middleware can be used for various purposes, such as handling asynchronous actions, logging, performing side effects, or applying transformations to the dispatched actions.

Redux-thunk

Redux Thunk is a middleware for Redux that allows you to write action creators that return functions instead of plain action objects. This enables you to perform asynchronous operations, such as making API requests, inside your action creators.

Install the necessary packages. You need to install both redux-thunk and redux libraries.

follow these steps:

                                
                                    
  npm install redux-thunk redux
                                
                            

Create your Redux store by applying the redux-thunk middleware using the applyMiddleware function from Redux.

                                
                                    
  import { createStore, applyMiddleware } from 'redux';
  import thunk from 'redux-thunk';
  import rootReducer from './reducers';
  const store = createStore(rootReducer, applyMiddleware(thunk));
                                
                            

Write an action creator that returns a function instead of an action object. This function can have side effects and can dispatch multiple actions asynchronously. It receives the dispatch and getState functions as arguments.

                                
                                    
  import axios from 'axios';
  const fetchUsers = () => {
    return (dispatch, getState) => {
      dispatch({ type: 'FETCH_USERS_REQUEST' });
      axios.get('/api/users')
        .then(response => {
          dispatch({ type: 'FETCH_USERS_SUCCESS', payload: response.data });
        })
        .catch(error => {
          dispatch({ type: 'FETCH_USERS_FAILURE', payload: error.message });
        });
    };
  };
                                
                            

The fetchUsers action creator returns a function that uses Axios to make an API request. It dispatches different actions based on the request status (e.g., request started, request successful, request failed).

CombineReducers

The combineReducers function is a utility provided by the Redux library that allows you to combine multiple reducers into a single root reducer. It simplifies the process of managing multiple parts of the state in a Redux application.

When an application grows and requires managing different parts of the state independently, you can create separate reducers for each part. combineReducers helps you bring these reducers together into a cohesive structure.

we have two separate reducers: todosReducer and userReducer. The combineReducers function is used to combine them into a single root reducer called rootReducer.

The combineReducers function accepts an object where each key represents a slice of the state and the corresponding value is the reducer responsible for managing that slice. In this case, the todos slice is managed by the todosReducer, and the user slice is managed by the userReducer.

Here's an example of how to use combineReducers:

                                
                                    
  function counterReducer(state = { value: 0 }, action) {
    switch (action.type) {
      case "counter/incremented":
        return { value: state.value + 1 };
      case "counter/decremented":
        return { value: state.value - 1 };
      default:
        return state;
    }
  }
  const rootReducer = combineReducers({
    todos: todosReducer,
    visibilityFilter: visibilityFilterReducer,
    counter: counterReducer,
  });
                                
                            

Conclusion

Redux allows you to manage your app's state in a single place and keep changes in your app more predictable and traceable. It makes it easier to reason about changes occurring in your app. But kindly note that all of these benefits come with tradeoffs and constraints. Hence you can follow the above steps to implement Redux in your React application.

Let's develop your ideas into reality