Deep Dive Into the useReducer() hook
Tags: react, frontend, webdev, javascript
Published: 2023-05-05 14:30:53

## Introduction
In React, `useReducer()` is one of the most important hooks. We use the `useState()` hook for **component-based state management**. That is good if your component only has two or three states. But if you have many states in the component, then `useReducer()` can be a better choice. 

## When to use it?
The initial setup of the `useReducer()` hook is overwhelming for beginners. But over time, it will make your code more **modular** and **readable**. If your code has more than four or five related states, instead of the `useState()`, use the `useReducer()` hook.

## How to use it?
There are several steps involved in defining the `useReducer()` hook. 
1. Build a **reducer function**.
2. Initialize the `useReducer()` hook.
3. **Dispatch** an event.

### 1. Build a reducer function:
Firstly, you need to write a **reducer function**. This function always gets two parameters. The first parameter is the **current state**, and the second is the **action**. In this **action**, we can pass any **payload**. This **action** is an **object** where we always pass a key called **type**. With this **type** parameter, we can check different conditions and return values based on it. These values are going to be the new value of the state variable. This reducer functions always needs to be a **pure function**. That means it will not produce any **side effects**. Below is an example of a **reducer**:
```javascript
function counterReducer(state, action) {
 switch (action.type) {
   case 'INCREMENT': {
     return state + 1;
   }
   case 'DECREMENT': {
     return state - 1;
   }
   default: {
     alert('You entered wrong action type');
     return 0;
   }
 }
}
```
### 2. Initialize the useReducer() hook:
In this step, `import` the `useReducer()` hook from `react`. Then, same as the `useState()`, declare a state. But, in the case of `useReducer()`, the first value is the **state**, and the second is a **state changer method** `dispatch`. We will discuss the `dispatch` in the next step. The `useReducer()` hook takes three parameters:
- Reducer Function.
- Initial Argument.
- Init function.

#### Reducer Function
It is the same **reducer function** we talked about earlier. We have to pass that **reducer function** as the **first parameter** of the `useReducer()` hook. 
#### Initial Argument
It is the **initial value** of the **state**. If the initial state is small, we declare it inside the `useReducer()` hook. Otherwise, we store values inside a **constant** and refer to that inside the `useReducer()` function.
#### Init function
It is an optional parameter. It is an **initializer function** which returns the value of the **initial state**. If it’s not specified, the **initial state** is set as the **initial argument**. Otherwise, the **initial state** is set to the result of calling `init(initialArg)`.
```javascript
const [count, dispatch] = useReducer(counterReducer, 0);
```
### 3. Dispatch an event
Let’s talk about the `dispatch` function. It is the second value while declaring the `useReducer()` hook. In the dispatch, we can pass an object. This object is the `action` parameter value of the `reducer` function. We always pass a `type` key inside the dispatch function. It helps us to check the condition and return the proper value for the `state`. Below are the two examples of incrementing and decrementing a counter with a `dispatch` function.
```javascript
const incrementCount = () => {
   dispatch({
     type: 'INCREMENT',
   });
 };


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

```
In large projects, we declare the **reducer function** in a different file and **export** it from there. As it is a **pure function**, declaring it outside the component doesn’t affect the `state`. Below is the complete example code of the **counter app**.
In the **App.js** file:
```javascript
import { useReducer } from 'react';
import { counterReducer } from './reducers';


const App = () => {
 const [count, dispatch] = useReducer(counterReducer, 0);


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


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


 return (
   <div className='container'>
     <h1 className='container-heading'>Counter App</h1>
     <section className='counter-container'>
       <h2 className='counter-value'>{count}</h2>
       <div className='button-container'>
         <button className='btn increment-btn' onClick={incrementCount}>
           +
         </button>
         <button className='btn decrement-btn' onClick={decermentCount}>
           -
         </button>
       </div>
     </section>
   </div>
 );
};


export default App;
```
In the **reducers.js** file,
```javascript
export function counterReducer(state, action) {
 switch (action.type) {
   case 'INCREMENT': {
     return state + 1;
   }
   case 'DECREMENT': {
     return state - 1;
   }
   default: {
     alert('You entered wrong action type');
     return 0;
   }
 }
}
```
## Summary
In this blog, we discussed the **useReducer() hook**, **when to use it**, **how to declare it** and **the things you need to keep in mind while using the useReducer() hook**. Follow me to learn more about **React** and other **Frontend Development skills**.