DEV Community

Joseph Mawa
Joseph Mawa

Posted on

What is useReducer hook and how do you use it?

Contents

Introduction to hooks

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. Today i am going to cover the basics of useReducer hook.

What is the useReducer hook?

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.

What arguments are passed to useReducer hook?

It takes three arguments and returns an array of two elements.

 const [state,  dispatcher] = useReducer(reducer, initArg, init);
Enter fullscreen mode Exit fullscreen mode

reducer

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.

    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
     }
 }
Enter fullscreen mode Exit fullscreen mode

It is not uncommon to see switch statement being used to determine action to take. More about action HERE . You can also use anonymous function to define reducer.

initArg

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.

init

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.

   function init(initArg){
      // Do some expensive computation
      // Return a value which is used for setting initial state
   }
Enter fullscreen mode Exit fullscreen mode

What is the return value of useReducer hook?

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:

    const [state, dispatch] = useReducer(reducer, initArg);
Enter fullscreen mode Exit fullscreen mode

How do you invoke dispatch?

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.

 dispatch({action: "add", value: 2})
Enter fullscreen mode Exit fullscreen mode

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.

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);
Enter fullscreen mode Exit fullscreen mode

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 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.

 dispatch({action: "add", value: 1});
Enter fullscreen mode Exit fullscreen mode

If you find this article useful, you can share it on Twitter. Someone might find it useful too or if you notice something which is technically inaccurate, you can leave a comment below.

REFERENCE

React Hooks API Reference

Top comments (1)

Collapse
 
joedotnot profile image
joedotnot

Your useEffect was easy to understand, this is not; Having read it, I still don't understand its Usage - You could have put some use cases and examples where it is useful (otherwise no point, I will just read the React officials docs ?)