Use Reducer hook
React provides several built-in hooks to help manage state in functional components.
Among them, useState is the go-to for simple states. But when your state logic becomes more complex — like involving multiple values or depending on previous state — useReducer can be a much better choice.
Although it’s powerful, useReducer is often underused by beginners because it sounds more complicated than it actually is.
In this article, I’ll walk you through a simple and beginner-friendly use case of useReducer — a classic counter example. By the end, you’ll understand how it works and when to use it.
useState is like a quick notepad. you write something your state and update directly
const [count, setCount] = useState(0);
setCount(count + 1); // update the stateuseState is suitable for simple functionalities, and easy to use. but it become messy with complex updates
useReducer is more like a decision-maker. You describe what you want (an action), and a function (called a reducer) decides how to update the state.
Let’s compare useState and useReducer using a basic counter example.
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<h2>Count: {count}</h2>
<button onClick={() => setCount(count + 1)}>+</button>
<button onClick={() => setCount(count - 1)}>-</button>
<button onClick={() => setCount(0)}>Reset</button>
</div>
);
}above the code is simple. But what if we had more actions ? the code become messy.
Here we see how to useReducer for above counter
1. Import Dependencies
first import dependencies from react library
import React, { useReducer } from 'react';
2. Define the Initial State
Get Ram’s stories in your inbox
Join Medium for free to get updates from this writer.
then define initial state
const initialState = { count: 0 };the initial state is your starting state, it’s an object with a single property count set to 0,
Why an object instead of just a number? Because using an object allows you to easily add more state values later without rewriting everything.
3. Create 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;
}
}this function takes two arguments, first one is the current state, second is an action, based on the action.type, it returns a new state.
in increment case increase count by 1, decrement state decrease it by 1 then reset sets it back to 0, default returns the existing state if the action is unknown (a safety fallback).
4. Build the Component
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);Here you call useReducer with reducer function and initial state value and it returns current state initially in state, and dispatch is a the function used to send actions that trigger the state updation.
5. Render the UI
return (
<div>
<h2>Count: {state.count}</h2>
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
<button onClick={() => dispatch({ type: 'reset' })}>Reset</button>
</div>
);
}Here displaying the count using {state.count}, then three buttons provide different actions by using dispatch to reducer, when you click a button, the reducer gets called with corresponding action, it update the state then react re-renders the component with the new state.
6. Export the Component
export default Counter;it allows you to use the counter component elsewhere in your app.
Simple Counter Example using useReducer
import React, { useReducer } from 'react';
// 1️⃣ Step 1: Define the initial state
const initialState = { count: 0 };
// 2️⃣ Step 2: Create 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️⃣ Step 3: Create the Counter component
function Counter() {
// useReducer gives us the current state and a dispatch function
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div style={{ textAlign: 'center', marginTop: '50px' }}>
<h2>Count: {state.count}</h2>
{/* Dispatch actions to update the state */}
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
<button onClick={() => dispatch({ type: 'reset' })}>Reset</button>
</div>
);
}
export default Counter;This example is a great starting point for learning useReducer. From here, you can expand it to manage more complex data like form inputs, to-do lists, or UI state.






