What is useReducer hook and how do you use it?
Tags: react, webdev
Published: 2020-06-26 20:54:54

<h1> Contents </h1>
<ul>
   <li> <a href = '#introduction'> Introduction to hooks </a> </li>
<li> <a href = '#about'> What is the useReducer hook? </a> </li>
<li> <a href = '#arg'> What arguments are passed to useReducer hook? </a> </li>
<li> <a href = '#return'> What is the return value of useReducer hook? </a> </li>
<li> <a href = '#dispatch'> How do you invoke dispatch? </a> </li>
<li> <a href = '#ref'> Reference </a> </li> 

</ul>

<h1 id = 'introduction'> Introduction to hooks </h1>
This is the second post of my React hooks series. If you haven't read the first one which covers the most basic react hook `useState`, check it out [here](https://dev.to/nibble0101/what-is-usestate-hook-and-how-do-you-use-it-3d71). Today i am going to cover the basics of `useReducer` hook.

<h1 id = 'about'> What is the useReducer hook? </h1>

A `hook` is a special function which enables one use state and other react features without writing ES6 class components which are generally considered confusing and difficult to master.

`useReducer` hook is part of the React hooks API. It is a function which can be used instead of `useState` if one is dealing with complicated state logic. 

<h1 id = 'arg'> What arguments are passed to useReducer hook?</h1>

It takes three arguments and returns an array of two elements.
```javascript
 const [state,  dispatcher] = useReducer(reducer, initArg, init);
```

<h2> reducer </h2>
The first required argument to `useReducer` is a function usually referred to as `reducer`. `reducer` takes two parameters: `state` and `action`.
`action` is used for specifying different ways state should be updated. `reducer` function takes the form below and it is usually defined before the component.
```javascript
    function reducer(state, action){
        if( action satisfies some condition){
           // Do something
           // Return new state
       }
       else if (action satisfies another condition) {
          // Do something
          // Return new state
      }else{ 
         // Do something
         // Return new state
     }
 }
```
It is not uncommon to see `switch` statement being used to determine action to take. More about `action` <a href = '#dispatch'> HERE </a>. You can also use anonymous function to define `reducer`.

<h2> initArg  </h2>

This is the second argument passed to `useReducer`. If the third argument `init` which is optional is omitted, `initArg` is set as the initial state otherwise  it is passed to `init`. 

<h2>  init </h2>

This is the third argument to `useReducer` and it is optional. It is a function passed to `useReducer` if the initial state is to be arrived at through, in most cases a computationally expensive process. This function is invoked with the second argument to `useReducer` `initArg` passed to it as an argument and its return value is used for setting the initial state. It takes the form below.
```javascript
   function init(initArg){
      // Do some expensive computation
      // Return a value which is used for setting initial state
   }
```

<h1 id = 'return'> What is the return value of useReducer hook? </h1>

`useReducer` returns an array of two elements. The first element of the array is the initial state and the second element of the returned array is the function you call if you want to specify what action to take. You can use array destructuring to give them meaningful names like:
```javascript
    const [state, dispatch] = useReducer(reducer, initArg);
```
<h1 id = 'dispatch'> How do you invoke dispatch? </h1>

You can invoke `dispatch` if you want to update state. It takes one argument used for specifying `action`. This argument is in most cases an object but it doesn't necessarily have to be. Passing an object enables you to specify an action as well as pass the data you need for setting/updating state.

```javascript
 dispatch({action: "add", value: 2})
```

In the call to `dispatch` above, action is "add" and it is a string constant though it doesn't necessarily have to be and data used for setting or updating state is passed as value of the object property `value`.

Code below illustrates how you can use `useReducer`.
```javascript
import React, { useReducer } from "react";
import ReactDOM from "react-dom";

function reducer(state, action) {
  switch (action.type) {
    case "add":
      return state + action.value;
    case "subtract":
      return state - action.value;
    default:
      return state;
  }
}

function App(props) {
  const [count, dispatch] = useReducer(reducer, 10);
  function increaseCountHandler(e) {
    dispatch({ type: "add", value: 1 });
  }
  function decreaseCountHandler(e) {
    dispatch({ type: "subtract", value: 1 });
  }
  return (
    <div>
      <p> {count}</p>
      <p>
        <button onClick={increaseCountHandler}> + </button>
      </p>
      <p>
        <button onClick={decreaseCountHandler}> - </button>
      </p>
    </div>
  );
}
const element = document.getElementById('root');
ReactDOM.render(<App />, element);
```
In the code above, i started by defining a reducer with two parameters: `state` and `action`. `state` is the current state and the `action` is an object which is passed to reducer using `dispatch`, the function returned after calling `useReducer`. Inside the `App` component, `reducer` function is passed to `useState` as first argument and initial state is set to 10. 

NOTE: I haven't passed the third optional argument `init` to `useReducer`. If we are to pass it, the second argument `10` will be used for invoking it and initial state is set to the return value.
[Array destructuring](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) has been used to unpack the return value of `useReducer`.

Take note of how `dispatch` is invoked in the event handlers. You invoke it with an object specifying `action` and `data` for updating state. 

```javascript
 dispatch({action: "add", value: 1});
```

If you find this article useful, you can share it on [Twitter](https://twitter.com/?lang=en). Someone might find it useful too or if you notice something which is technically inaccurate, you can leave a comment below. 

<h1 id = 'ref'> REFERENCE </h1>
[React Hooks API Reference](https://reactjs.org/docs/hooks-reference.html)