How to use the useReducer hook in React

·

3 min read

How to use the useReducer hook in React

Introduction

The useReducer() hook is used to manage the state of a component. It's an alternative to the useState() hook.

The useReducer() can handle complex state logic more elegantly than useState(). It separates the state manipulation logic from the component and this makes the component less verbose and lighter.

Syntex

import {useReducer} from 'react';

function Counter(){
    const [state, dispatch] = useReducer(reducerFn, initialState);
    // ....
}

Returned Value

The useReducer() returns an array with two values:

  • state: It represents the state value.

  • dispatch function: It's a function that we call when we need to update the state. It takes an action object as an argument. The action object describes what action we want to perform on the state, like a decrement or increment of the count value.

       const increment = () => {
          dispatch({ type: 'INCREMENT' });
       };
    

Arguments

The useReducer takes two arguments:

reducerFn: This is the function that contains the state updation logic. It accepts two parameters: state and action. Based on the action type it updates the state.

// Reducer function
const 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;
  }
};

When we dispatch an action, the reducer function is called with the current state and the action. It determines the new state based on the action type and returns the updated state.

The reducer function updates state in immutable manner. If we try to update state directly, React may not be able to detect changes and won't re-render the component.

  • InitialState: It represents the initial value of the state.

      //...
      const initialState = { count: 0  };
      function Counter(){
          const [state, dispatch] = useReducer(reducerFn, initialState);
          // ....
      }
    

Example

import React, { useReducer } from 'react';

// Reducer function
const 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;
  }
};

const Counter = () => {
  // Initialize state using useReducer
  const [state, dispatch] = useReducer(reducer, { count: 0 });

  // Event handlers
  const increment = () => {
    dispatch({ type: 'INCREMENT' });
  };

  const decrement = () => {
    dispatch({ type: 'DECREMENT' });
  };

  const reset = () => {
    dispatch({ type: 'RESET' });
  };

  return (
    <div>
      <h1>Count: {state.count}</h1>
      <button onClick={increment}>Increment</button>
      <button onClick={decrement}>Decrement</button>
      <button onClick={reset}>Reset</button>
    </div>
  );
};

export default Counter;

In this example, we have a simple Counter component. The reducer function defines the state transitions based on the action type provided. The initial state is { count: 0 }.

To update states, we have defined event handlers,(increment, decrement, and reset) that dispatch actions to the reducer based on user interactions.

When an action is dispatched, the reducer function is called with the current state and the action. It determines the new state based on the action type and returns the updated state.

Conclusion

The useReducer(reducer, initialState) hook is used to manage complex states and helps to write the state updation logic separately.

We use the dispatch(action) function to update the state and the reducer(state, action) function updates the state based on the action type.