How to Implement useReducer Hook in React

Managing complex state in React can become difficult with the standard useState Hook. This article provides a straightforward guide on how to implement the useReducer Hook in React, explaining its core components—the reducer function, initial state, and dispatch actions—along with a practical step-by-step code example to help you manage state transitions efficiently.

Understanding useReducer Syntax

The useReducer Hook is alternative to useState that is best suited for managing state objects that contain multiple sub-values or when the next state depends on the previous one.

The basic syntax of useReducer is:

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

Step-by-Step Implementation

To implement useReducer in your React component, follow these four basic steps.

Step 1: Define the Initial State

Start by declaring the initial state of your component. This is typically represented as an object.

const initialState = { count: 0 };

Step 2: Create the Reducer Function

The reducer function accepts the current state and an action object, and returns the new state. A switch statement is commonly used to handle different action types.

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    case 'reset':
      return { count: 0 };
    default:
      throw new Error(`Unhandled action type: ${action.type}`);
  }
}

Step 3: Initialize the Hook in Your Component

Call the useReducer hook inside your functional component, passing the reducer function and the initial state as arguments.

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

Step 4: Dispatch Actions to Trigger State Updates

Use the dispatch function inside your event handlers to trigger state updates. Pass an action object that contains a type property (and any optional payload).

<button onClick={() => dispatch({ type: 'increment' })}>Increment</button>

Complete Code Example

Below is a complete, working example of a counter component implemented using the useReducer Hook.

import React, { useReducer } from 'react';

// 1. Define the initial state
const initialState = { count: 0 };

// 2. Define the reducer function
function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    case 'reset':
      return { count: 0 };
    default:
      return state;
  }
}

// 3. Create the Component
function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <div style={{ textAlign: 'center', marginTop: '50px' }}>
      <h1>Count: {state.count}</h1>
      <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
      <button onClick={() => dispatch({ type: 'reset' })} style={{ margin: '0 10px' }}>Reset</button>
      <button onClick={() => dispatch({ type: 'increment' })}>+</button>
    </div>
  );
}

export default Counter;

When to Use useReducer Instead of useState

While useState is ideal for simple state values like strings, booleans, or numbers, useReducer is the preferred choice when: