1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Understanding React useReducer

Posted at

For developers who started learning React, useReducer is very important to know because it helps to manage complex state logic in React applications which is an alternative to useState.

What is useReducer?

Before you dive into useReducer, let’s go back and look at what a reducer is.

What is reducer?

A reducer is a very simple idea and it’s something that will be easy for you to grasp because, in a nutshell, it’s just a simple JS function.

A reducer is a function which takes two arguments — the current state and an action — and returns based on both arguments a new state.

We can express the idea in a single line, as an almost valid function:

.js
const initialState = [];

const itemReducer = (state = initialState, action) => {
   switch(action.type) {
      case 'add':
         return [...state, action.payload];
      case 'remove':
         return state.filter(i => i.id != action.payload.id);
      default:
         return state;
   }
}

What reducer is doing here?

The above reducer is adding and removing the item to the items property from state based on the action type passed.

Okay, let’s back to useReducer.
The useReducer hook is used to store and update states just lik useState hook. It accepts a reducer and initial state like above example, and returns the new version of state and the dispatch function to which you can pass an action and later invoke it.

Let's take a lookup to useRecuder with practical sample code.
The scenario is to handle counter state like increasing, decreasing and resetting the count.

.js
import React, { useReducer } from 'react';

const ACTIONS =  {
    'INCREASE': 'increase',
    'DECREASE': 'decrease',
    'RESET': 'reset'
};

export function counterReducer(state, action) {
    switch(action.type) {
        case ACTIONS.INCREASE:
            return {
                count: state.count + 1
            };
        case ACTIONS.DECREASE:
            return {
                count: state.count - 1
            };
        case ACTIONS.RESET:
            return {
                count: 0
            };
        default:
            return state;
   }
}

const INITIAL_STATE = {
    count: 0
};

export function Counter() {
    const [state, dispatch] = useReducer(counterReducer, INITIAL_STATE);
    const increaseHandler = () => {
        dispatch({ type: ACTIONS.INCREASE });
    };
    const decreaseHandler = () => {
        dispatch({ type: ACTIONS.DECREASE });
    };
    const resetHandler = () => {
        dispatch({ type: ACTIONS.RESET });
    };

    const style = {
        'margin-right': '10px'
      };

    return (
        <div>
            <div>
                <button style={style} onClick={increaseHandler}>+</button>
                <label style={style}>{state.count}</label>
                <button onClick={decreaseHandler}>-</button>
            </div>
            <div style={{'margin-top': '5px'}}>
                <button onClick={resetHandler}>Reset</button>
            </div>
        </div>
    );
}

The reducer function

This is to update the component’s state when some actions occur. This function tells what the state should do depending on the action. It returns an object, which is then used to replace / change the state.

It takes in two arguments which are a state and an action; wherein state is nothing but your application’s current state, and the action is an object which contains the details of all the actions currently happening.

.js
export function counterReducer(state, action) {
    switch(action.type) {
        case ACTIONS.INCREASE:
            return {
                count: state.count + 1
            };
        case ACTIONS.DECREASE:
            return {
                count: state.count - 1
            };
        case ACTIONS.RESET:
            return {
                count: 0
            };
        default:
            return state;
   }
}

The initial state

This is the default value of the component’s state when it gets mounted for the first time inside the application.

.js
const [state, dispatch] = useReducer(counterReducer, INITIAL_STATE);

Dispatching Action

Dispatch is just like a function which you can pass around to other components through props.You must have noticed that useReducer returns two values in an array. The first one is the state object, and the second one is a function called dispatch. This is what is used to dispatch an action.

.js
const increaseHandler = () => {
    dispatch({ type: ACTIONS.INCREASE });
};
const decreaseHandler = () => {
    dispatch({ type: ACTIONS.DECREASE });
};
const resetHandler = () => {
    dispatch({ type: ACTIONS.RESET });
};

The result is as the following after the counter is implemented with useReducer.

image.png

Summary
I hope this helps you to understand how to use useReducer. There are a lot more we can do with it altough the example is just simple.
Thank you so much for reading. I will try to share more about React based on my experience and knowlege.
I'm hoping your discussion regarding the blog in the comment section below.

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?