Complete guides to React useReducer() Hook 
Tags: react, javascript, redux, beginners
Published: 2021-09-05 13:51:44

`useReducer()` is a React.js Hook which manage complex state in your application and update it based on the 'action' you send to.
It's used as an alternative for `useState` if you have a complex states or can be used both together according to your application requirements.
It's very similar to `Redux` if you want to not use a 3rd-party library.
<br/>
<h2>First</h2>

You should import `useReducer` from react js
```
import React, { useReducer } from 'react';
```
<h2>Second :</h2>
`useReducer` Hook accepts a reducer function, and an initial state.
It's returns an array with 2 values:
The first one is the `state` value, and the second value is the `dispatch` function which is used to trigger an action with the help of ES6 destructuring.  
```
const [state, dispatch] = useReducer(reducer, initialState);
```
<h5>initialState :</h5>
The initial state that we want to start working on it

<h5>reducer :</h5>
Which we'll use to manipulate our state.

<h1>Let's go with simple example</h1>
Let's say you're displaying some products in your app, and you want to :

- Add a product to the cart when user click on `add to cart` button and list it in cart page.
- Remove the product from cart list if the user click on `remove from cart` button.
- User can switch the application (dark/light mode)

*Create `Reducer.js` component to add our reducer in it.*
<h2>How to use it ?</h2>
- Firstly, we will define the reducer function that will manipulate our state:
```
// Reducer.js
const reducer = (state, action) => {
  // reducer function accepts two arguments 
  /* 
   the first one is `state` which is going to be the state 
   before the update.
  */ 
  /* 
   the second one is `action` which is what are we trying to do.
  */ 
}

export default reducer;
```
- Second step, we will define the initial state object which contains our initial values :
  <p>1- `cart` array property which holds products user added to his/her cart.</p>
  <p>2- `mode` property which holds the app mode and it's by default will be `light`.</p>

We'll put those in our file, but outside of the component:

```
// Reducer.js
export const initialState = {
    cart: [],
    mode: 'light'
};

const reducer = (state, action) => {
    switch (action.type) {
        case 'ADD_TO_CART':
            return {
                ...state,
                cart: [...state.cart, action.item]
            };

        case 'REMOVE_FROM_CART':
            const index = state.cart.findIndex(item => action.id === item.id);
            let newCart = [...state.cart];
            if (index >= 0) {
                newCart.splice(index, 1);
            }

            if (newCart.length === 0) {
                return {
                    ...state,
                    cart: newCart,
                }
            } else {
                return {
                    ...state,
                    cart: newCart,
                }
            };
        case 'CHANGE_MODE':
            return {
                ...state,
                mode: action.mode
            }
        default: return state
    }

}

export default reducer;
```

Now, let's imagine we have a `Product.js` component that return a products to be displayed in your app.
```
// Product.js
import React from 'react'

function Product({ name, image }) {
    const addToCart= () => {
        // some code
    }
    return (
        <div className="product">
            <img src={`${image}`} />
            <p>{name}</p>
            <button onClick={addToCart}>add to cart</button>
        </div>
    )
}

export default Product

``` 
- The fourth step, our reducer is all setup, now let's define then use it.
To be able to use the reducer function you must define it in everywhere you need like so:
```
import React, {useReducer} from 'react'
import reducer, {initialState} from './Reducer';

function Product({ name, image }) {
    const [state, dispatch] = useReducer(reducer, initialState) ;
    .
    .
    .
```
Firstly you need to import `useReducer` from React, then import the `reducer` and `initialState` to be used.
Now we will define our reducer using `useReducer()` hook
```
const [state, dispatch] = useReducer(reducer, initialState) ;
```
The useReducer hook will return two things in an array: the state, and a dispatcher to update the state.

We will grab those with array destructuring, similar to state and setState with the useState.

<h2>Dispatch actions :</h2>

Every time the user clicks on `add to cart` button, `addToCart` function will be called to **dispatch** the action to the reducer function to do some changes in that state.
So, the `addToCart` function will contains the following code :

```
const addToCart= () => {
        dispatch({
            type: 'ADD_TO_CART',
            item: {
                image,
                name
            }
        })
    }
```

We sent the action name to the reducer function to know what kind of changes will be happened, in this case the action is `ADD_TO_CART` action. Also we sent the item or the product which user need to add to the card to be added to the `state.cart` array.

So, the `Product.js` component will be :

```
import React, {useReducer} from 'react'
import reducer, {initialState} from './Reducer';

function Product({ name, image }) {
    const [state, dispatch] = useReducer(reducer, initialState) ;
    const addToCart= () => {
        dispatch({
            type: 'ADD_TO_CART',
            item: {
                image,
                name
            }
        })
    }
    return (
        <div className="product">
            <img src={`${image}`} />
            <p>{name}</p>
            <button onClick={addToCart}>add to cart</button>
        </div>
    )
}

export default Product

```
> We will be satisfied with ADD_TO_CART, others actions will be the same but with deferent functionality

<h2>Accessing state</h2>

Now you can accessing the state and make on it anything you want like mapping cart array and so on.

##Conclusion##

- useReducer Hook is extremely useful when working on complex and different states depend on each other.

- useReducer is very similar to Redux if you want to not use a 3rd-party library or if it's only for a component or two.

Hope this article helped you to understand useReducer hook what is exactly.

Thanks for reading 🙌
-Ahmad Mukahal