Unleashing the Power of useReducer in React: A Simple Counter Example

Rahul DasuRahul Dasu
3 min read

When building React applications, managing state efficiently is crucial for creating interactive and responsive user interfaces. While the useState hook is commonly used for handling simple state transitions, the useReducer hook provides a more robust solution for managing complex state logic. In this blog, we'll explore the power of useReducer by walking through a simple example of a counter application.

Why useReducer?

The useReducer hook is a powerful alternative to useState for managing state in React. It is particularly useful when:

  • You have complex state logic that involves multiple sub-values.

  • The next state depends on the previous state.

  • You want to centralize and organize your state logic for better maintainability.

useReducer helps in separating the state management logic from the component, making the code more readable and testable. It follows the reducer pattern, which is also used in libraries like Redux.

The Counter Example

Let's dive into a simple counter example to understand how useReducer works.

Initial Setup

First, we need to import the useReducer hook from React:

import { useReducer } from "react";

Next, we'll define our initial state and action types:

const INITIAL_STATE = {
  count: 0,
};

const ACTIONS = {
  INCREMENT: 'increment',
  DECREMENT: 'decrement',
};

Reducer Function

The reducer function takes the current state and an action as arguments, and returns the new state based on the action type:

function reducer(state, action) {
  switch (action.type) {
    case ACTIONS.INCREMENT: {
      return { count: state.count + 1 };
    }
    case ACTIONS.DECREMENT: {
      return { count: state.count - 1 };
    }
    default:
      return state;
  }
}

Component with useReducer

In our component, we'll use the useReducer hook to manage the counter state:

export default function App() {
  const [state, dispatch] = useReducer(reducer, INITIAL_STATE);

  const incrementCounter = (e) => {
    dispatch({ type: ACTIONS.INCREMENT });
  };

  const decrementCounter = (e) => {
    dispatch({ type: ACTIONS.DECREMENT });
  };

  return (
    <div>
      <button onClick={decrementCounter}>
        -
      </button>
      <p>{state.count}</p>
      <button onClick={incrementCounter}>
        +
      </button>
    </div>
  );
}

How It Works

  1. Initial State: The useReducer hook initializes the state with INITIAL_STATE.

  2. Dispatching Actions: The dispatch function is used to send actions to the reducer. The incrementCounter and decrementCounter functions dispatch the INCREMENT and DECREMENT actions, respectively.

  3. Reducer Logic: The reducer function handles the dispatched actions and returns the new state. When the INCREMENT action is dispatched, the count is incremented by 1. When the DECREMENT action is dispatched, the count is decremented by 1.

  4. Rendering: The component renders the current count and buttons to increment and decrement the count. Clicking the buttons triggers the respective functions, updating the state via the reducer.

Conclusion

The useReducer hook is a powerful tool for managing complex state logic in React applications. By centralizing state transitions in a reducer function, you can keep your components clean and maintainable. This simple counter example demonstrates how useReducer can be used to handle state updates in a predictable and scalable manner.

Next time you find yourself dealing with intricate state management in your React app, consider giving useReducer a try!

0
Subscribe to my newsletter

Read articles from Rahul Dasu directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Rahul Dasu
Rahul Dasu

Software Engineer