DEV Community

Kolapo Wariz
Kolapo Wariz

Posted on

useReducer Hook in React

A software developer writing code on his laptop

Introduction

The useReducer Hook was introduced as a hook in React version 16.8 which was released on the 16th of February 2019, it's a hook in React that allows us to handle complex state logic and action. This hook draws inspiration from the Redux state management pattern and exhibits some similarities in its behavior.
You might be asking yourself, "Don't we already have the useState hook for state management in React?"
Absolutely! When dealing with state management in React, the useState hook is suitable for basic use cases. However, for more complex scenarios requiring global state management, combining the useReducer hook with useContext can provide a more structured approach similar to Redux. In such cases, it may be a more preferable alternative to using additional libraries like Redux.

Prerequisite

  • IDE (vscode, zed or stackblitz)
  • JavaScript ES6
  • Basic knowledge on the useState Hook

In this article, you will learn:

  • Reduce method in array.
  • What is the useReducer Hook in react?
  • Reducer Function.
  • Using the reducer function with the useReducer Hook.
  • Building a simple counter app with the useReducer Hook.

Reduce method in array.

To start using useReducer, it's essential to understand how the Reduce method in JavaScript's built-in Array works, as it shares remarkable similarity with the useReducer hook.
The reduce() method carries out a custom "reducer" callback function on every element within an array and then produces a single value. This final output is the result of applying the reducer across all elements in the array.

Syntax

array.reduce(callbackFn)
array.reduce(callbackFn, initialValue)
Enter fullscreen mode Exit fullscreen mode

Let's take a look at the reduce function in action.

1. Create a simple array of elements;

const arr = [1, 3, 5, 7];
Enter fullscreen mode Exit fullscreen mode

2. Create a function that adds up all the elements in the array and will be used as the reducer function

const arr = [1, 3, 5, 7];

function add (a, b) {
  return a + b;
}
Enter fullscreen mode Exit fullscreen mode

3. Call the reduce method on the array and pass the add function as a callback

const arr = [1, 3, 5, 7];

function add (a, b) {
  return a + b;
}

const output = arr.reduce(add);

console.log(output)
Enter fullscreen mode Exit fullscreen mode

What is the useReducer Hook in react?

In React, the useReducer is a Hook used to manage state using a reducer function. It is an alternative to the useState hook and is particularly useful for managing more complex state logic. Similar to useState, useReducer lets you create state-like variables that cause the UI to be updated whenever they change.

The useReducer takes two arguments which are the reducer function and the initial state. The useReducer Hook also returns an array of two items: the current state and the dispatch function.

const state = useReducer[0]
const dispatch = useReducer[1]
Enter fullscreen mode Exit fullscreen mode

Using array destructuring which is a best practice, we can simplify the above :

const [state, dispatch] = useReducer(reducer, intialState)
Enter fullscreen mode Exit fullscreen mode

The dispatch function sends actions to the reducer function, which then updates the state based on the action received. The dispatch function is an integral part of the useReducer hook.

An action is an object that typically contains a 'type' property (which describes what kind of action it is) and any additional data needed to update the state. For example, when a button is clicked, an action with a specific type is sent to the reducer function. The reducer function updates the state based on the action type. To use the useReducer hook, import it from react.

useReducer Hook syntax

import { useReducer } from 'react';

function App() {
  const [state, dispatch] = useReducer(reducerFn, initialValue);
}
export default App;
Enter fullscreen mode Exit fullscreen mode

Managing state with reducers is slightly different from directly setting state. Instead of telling React “what to do” by setting state, you specify “what the user just did” by dispatching “actions” from your event handlers.

Reducer Function

A reducer function uses a useReducer hook to manage state updates predictably and concisely. It takes two parameters, the current state which is the state before the update, and an action which is an object that describes what change to make.
The action has a type property and can include additional data necessary for the update. The reducer function returns a new state based on the current state and action.

Reducer function syntax

const reducerFn = (state, action) => {
  // codes
  switch (action.type) {
    case 'something':
      return {
        ...state,
        //modifications for something
      };
    default:
      return state;
  }
};
Enter fullscreen mode Exit fullscreen mode

Using the reducer function with the useReducer Hook.

Here are the three necessary steps.

1. Define an initial state.

const initialState = {count: 0}
Enter fullscreen mode Exit fullscreen mode

2. Write a reducer function.

const reducer = (state, action) => {
  if (action.type === 'increase') {
    return { count: state.count + 1 };
  }
  return state;
};
Enter fullscreen mode Exit fullscreen mode

3. Use the 'useReducer' hook.

import { useReducer } from 'react';
const App = () => {
  const [state, dispatch] = useReducer(reducer, initialValue);
  const increaseCount = () => {
    dispatch({
      // action
      type: 'increase',
    })
  };

  return (
    <div>
      <p>{state.count}</p>
      <button onClick={increaseCount}>Increase</button>
    </div>
  )
};
Enter fullscreen mode Exit fullscreen mode

Building a simple counter app with the useReducer Hook.

import { useReducer } from 'react';

const initialValue = { count: 0 };

const reducer = (state, action) => {
  if (action.type === 'increasePlusOne') {
    return { count: state.count + 1 };
  } else if (action.type === 'decreaseMinusOne') {
    return { count: state.count - 1 };
  } else if (action.type === 'resetToZero') {
    return { count: 0 };
  }
  return state;
};

function App() {
  const [state, dispatch] = useReducer(reducer, initialValue);

  function increment() {
    dispatch({
      //action
      type: 'increasePlusOne',
    })
  }
  function decrease() {
    dispatch({
      type: 'decreaseMinusOne',
    })
  }

  return (
    <>
      <p>Hello</p>
      <p>useReducer count = {state.count}</p>
      <button onClick={increment}>Increase</button>
      <button onClick={decrease}>Decrease</button>
      <button onClick={() => dispatch({ type: 'resetToZero' })}>Reset</button>
    </>
  )
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Check out the StackBlitz code demonstrating the steps in the link below.

Conclusion

Using the reducer can keep component logic organized rather than using multiple 'useState' hooks. It also makes state transitions easy and predictable to understand. Use the reducer when the state logic is complex and involves a lot of sub-values. Reducer can also be used when the next state depends on the previous state.

Top comments (0)