Understanding the useReducer Hook in React

By Łukasz Kallas
Picture of the author
Published on
react image

What is useReducer?

The useReducer hook is a function that takes two or three arguments: a reducer function and an initial state, and optionally a initializer. It returns a pair: the current state and a dispatch function to send actions to update the state.

Syntax:

const [state, dispatch] = useReducer(reducer, initialState, initializer?)
  • reducer: A function that determines the next state based on the current state and an action.
  • initialState: The initial state value.
  • initializer: A function returning initialState.

Basic Example

Let's look at a simple counter example using useReducer:

import { useReducer } from 'react'

const initialState = { count: 0 }

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 }
    case 'decrement':
      return { count: state.count - 1 }
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState)

  return (
    <div>
      <p>Count: {state.count}</p>
      <button onClick={() => dispatch({ type: 'increment' })}>Increment</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button>
    </div>
  )
}

export default Counter

How useReducer Works

  1. Initial State: useReducer takes an initial state object, which in our example is { count: 0 }.
  2. Reducer Function: The reducer function accepts the current state and an action object. It returns a new state based on the action type. In the example above, the reducer handles two types of actions: 'increment' and 'decrement'.
  3. Dispatch: The dispatch function allows you to send an action to the reducer. It takes an action object as its argument, such as { type: 'increment' } or { type: 'decrement' }.

Why Use useReducer?

  • Complex State Logic: When you have multiple, related state variables that should be updated together, useReducer provides a more organized way to manage them.
  • Readability and Maintainability: With useReducer, all state transitions are centralized in the reducer function, making the component logic easier to understand and maintain.
  • Predictable State Updates: The use of a reducer function leads to predictable state updates, which is particularly useful when debugging.

Stay Tuned

Want to learn?
The best articles, links and news related to software development delivered once a week to your inbox.