How to use useReducer in React.js and JavaScript? Example Tutorial

Introduction

Before the React hooks were introduced, it was not possible to use state in functional components. The React hooks transformed stateless functional components into stateful components in which state and lifecycle methods like functionality could be used. 


The useState hook is the primary hook for declaring the state in a functional component. Using it, a state variable can be declared and initialized along with a function to manipulate it. But sometimes state gets complex and the useState hook is not efficient to handle it.


So React provides another hook for complex state management in functional components. This hook is called useReducer. In this article, we will discuss what useReducer hook is and how to use it. 



What is useReducer?

The useReducder hook is used to manage complex states in a functional component. It is quite similar to the useState hook but along initial state, it requires a reducer. Moreover, instead of a function, it declares a dispatch function. So, it has a redux-like pattern. 


A reducer is a pure function. It takes state and action as arguments and returns a new state. It must not do anything else, meaning there should be no side effects.


So basically, by using the useReducer hook, we can access the reducer from the component without even setting up redux.


Following is the syntax of the useReducer hook.


const [state, dispatch] = useReducer(reducer, initialState, init)


As mentioned earlier, the useReducer hook declares a state variable and a dispatch function. It has three arguments:


  • reducer to return a new state

  • initialState is the initial value of the state

  • init is used for lazy state initialization


Let’s understand with the help of an example. 





Observe the following initial state. 


const initialState = {

  total: 50000,

  withdrawn: 0,

  added: 0,

};


In the above state, “withdrawn” and “added” are dependent on the “total”. So, using the useState hook is not efficient in such a case. In the application, we will have two buttons, one for withdrawing 500$ and the other for adding 1000$. The value will be deducted or added to the “total” according to the button click. Moreover, we will track how much money was withdrawn and added by displaying it on the UI. 


Observe the reducer. 


const reducer = (state, action) => {

  switch (action.type) {

    case "WITHDRAW_500":

      return {

        ...state,

        total: state.total - 500,

        withdrawn: state.withdrawn + 500,

      };

    case "ADD_1000":

      return {

        ...state,

        total: state.total + 1000,

        added: state.added + 1000,

      };

    default:

      return state;

  }

};

 

export default reducer;


It is a typical redux reducer that can have two types of actions - “WITHDRAW_500” and “ADD_1000”. The state is not mutated directly, thus, taking care of the redux rules. We will use this reducer with the useReducer hook.






Observe the App.js file. 


import { useReducer } from "react";

import reducer from "./reducer";

 

export default function App() {

  const initialState = {

    total: 50000,

    withdrawn: 0,

    added: 0,

  };

 

  const [balance, dispatch] = useReducer(reducer, initialState);

 

  return (

    <div className="App">

      <button onClick={() => dispatch({ type: "WITHDRAW_500" })}>

        Withdraw 500$

      </button>

      <button onClick={() => dispatch({ type: "ADD_1000" })}>

        Add 1000$

      </button>

      <br />

      <h3>Total amount: {balance.total} </h3>

      <h3>Amount withdrawn: {balance.withdrawn} </h3>

      <h3>Amount added: {balance.added} </h3>

    </div>

  );

}


First, observe the line where the useReducer hook is used. 


const [balance, dispatch] = useReducer(reducer, initialState);


The reducer is passed as the first argument along with the initial state. Now, to update the state, the dispatch is required to fire the actions accordingly. 

 

<button onClick={() => dispatch({ type: "WITHDRAW_500" })}>

  Withdraw 500$

</button>

<button onClick={() => dispatch({ type: "ADD_1000" })}>

  Add 1000$

</button>


With every button, action will be dispatched. Remember, the “type” property is mandatory because according to it only the reducer will return a new state. 


When an action is dispatched, the state is updated. “balance” declared with useReducer is where the state is stored. Let’s check its initial value in the console. 



After the “Withdraw 500$” button is clicked.



After the “Add 1000$” button is clicked. 



So the state is being changed according to the button click. Finally, let’s display the state in the UI. 


<h3>Total amount: {balance.total} </h3>

<h3>Amount withdrawn: {balance.withdrawn} </h3>

<h3>Amount added: {balance.added} </h3>


Let’s check the output. 


How to use useReducer in React.js and JavaScript? Example Tutorial


This is how useReducer is used to manage complex states instead of useState. 



That's all about useReducer hook in react.js. The useReducer hook is a useful alternative to the useState hook when the state is complex or inter dependable. It uses a reducer to update the state and provides a dispatch method to fire actions. In this article, we discussed how to the useReducer hook to manage state in a functional component. 



Other Web development articles you may like to exploreThanks for reading this article so far. If you find these React.js and Javascript tutorials useful then please share them with your friends and colleagues. If you have any questions or feedback then please drop a note.
P. S. - If you don't mind learning from free resources like free online courses, books, and tutorials then you can also check out this list of 5 free resources to learn web development, in which I have shared some useful free resources for web developers.


No comments:

Post a Comment

Feel free to comment, ask questions if you have any doubt.