DEV Community

piyush
piyush

Posted on

Simple guide to useReducer in react.

I was using useState for state management for my react app. It was all fine and good until I had to manage more than three states on a single click. Sometimes the state required multiple operations which made it even more complex.

What exactly is useReducer?

useReducer is used to manage state ,as an alternative to useState, when the state becomes complex that involves multiple subvalues.

I prefer using useReducer ,when I have three or more states, to manage all the state mutations in one place.

Prerequisites:

Switch statement,
Spread operator,
useState.

How does it work?

First lets see how reduce in JavaScript works.
The reduce function executes a reducer function takes in an array and returns a single value. Here we have used reduce function + spread operator to add odd and even number of an array.

const reducer = (accumulator, currentValue) => 
{
return currentValue%2===0?
{...accumulator,even:accumulator.even+currentValue}:
{...accumulator,odd:accumulator.odd+currentValue}
}

[3, 4, 7, 8].reduce(reducer,{odd:0,even:0})
Enter fullscreen mode Exit fullscreen mode

We use spread operator to get the previous value
{...accumulator} of the object.

then will manipulate the object depending on whether the current value is odd or even.

{even:accumulator.even+currentValue}. Here, accumulator.even -> is the even value that was stored previously in accumulator object and currentVaulue is the current item of the array that is being passed through the reduce function.
The reducer function will return us one value. {odd:10,even:20}

Initalizing useReducer

const [state,dispatch]=useReducer(reducerFunction,stateVariables)
Enter fullscreen mode Exit fullscreen mode

In React, useReducer essentially accepts a reducer function
and returns a state object that we can bind components to and a dispatch function that we send actions to.

state variables:

State variables is the data we create in order to manipulate them.

For example in useState we pass the value directly

value=0
const [oddSum,setOddSum]=useState(value)
const [evenSum,setEvenSum]=useState(value)

Enter fullscreen mode Exit fullscreen mode

In reducer we create an object first

const stateVariables={
value:0
}
Enter fullscreen mode Exit fullscreen mode

The values in the state variables are manipulated with the help of the reducer function.

Reducer Function:

The reducerFunction accepts two parameters state and action.
The state is the data {the stateVariable that we created while creating useReducer} that we will manipulate
The function receives action from the the component where dispatch function is passed.

function reducerFunction(state,action){
////
}
Enter fullscreen mode Exit fullscreen mode

Passing function in the component.

In the dispatch function ,in our component ,we pass values "type" and "payload".

The possible action is determined by "type" that is passed within dispatch function.

And any specific values/information/data/object is passed through the payload and used to manipulate the stateVariables.

For example

<button onClick=()=>dispatch({type:"incrementHandler",payload:10})>
Increment by 10
</button>

<button onClick=()=>dispatch({type:"decrementHandler",payload:10})>
Decrement by 10
</button>

<button onClick=()=>dispatch({type:"reset"})>
Reset</button>

Enter fullscreen mode Exit fullscreen mode

Afterall reducer function is basically a switch statement defining all the possible actions a context can perform, and only updating the part of the global state related to that action

for example :

  function reducerFunction(state,action){
    switch(action.type){
      case "incrementHandler" :
        return {...state,value:state.value+action.payload}
    case "decrementHandler" :
        return {...state,value:state.value-action.payload}
    case "reset":
        return {...state,value:0}
  default:
       return {...state}

    }  
  }

Enter fullscreen mode Exit fullscreen mode

Here:
return {...state,value:state.value+action.payload}
we are using a spread operator to retrieve the previous
values in the state object and assign a new value to "value".

state.value will get the value in the previous state and add it with action.payload

i.e action.payload for type: "increment" and "decrement" is 10 so when I
click on Increment : value =0+10=10
click on Increment : value= 10+10=20
click on Decrement : value= 20-10=10
click on reset: value=0
etc.

Code snippet .

import { useReducer } from "react";
export default function App() {
  function reducerFunction(state, action) {
    switch (action.type) {
      case "incrementHandler":
        return { ...state, value: state.value + action.payload };
      case "decrementHandler":
        return { ...state, value: state.value - action.payload };
      case "reset":
        return { ...state, value: 0 };
      default:
        return { ...state };
    }
  }

  const stateVariables = {
    value: 0
  };
  const [state, dispatch] = useReducer(reducerFunction, stateVariables);

  return (
    <div className="App">
      <button
        onClick={() => dispatch({ type: "incrementHandler", payload: 10 })}
      >
        Increment by 10
      </button>
      <button
        onClick={() => dispatch({ type: "decrementHandler", payload: 10 })}
      >
        Decrement by 10
      </button>
      <button onClick={() => dispatch({ type: "reset" })}>Reset</button>
      <div>{state.value}</div>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

Oldest comments (0)