mohan's blog

mohan's blog

useReducer() Simplified

Before we dive into the main topic, let's take a moment to think about this. When you use react, there were obviously moments where the state becomes too complex to manage and the code becomes a mess managing it. To solve this problem, the useReducer() hook got introduced.

useReducer() hook

The useReducer() hook takes initialState & a reducer function and provides us with state and dispatch. Whenever we call dispatch, the dispatch automatically invokes the reducer function. We can pass numbers/strings/arrays/objects etc, to the dispatch function. These arguments are automatically accessed by the reducer function through its second parameter( action ).The reducer function usually has two parameters i.e., the first one being state and the second being action. The reducer's first parameter directly refers to the state and internally has access to the state. The second parameter action takes values from the dispatch's arguments. The reducer function takes the current state and performs an action on it and returns the new state.

current state + action = new state

const [state, dispatch] = useReducer(reducer, initialState);

Let's understand this better with the help of an example.

import "./styles.css";
import { useReducer } from "react";

const initialState = {
  name: "abc",
  occupation: "student",
  age: 19
};

const reducer = (state, action) => {
  switch (action.type) {
    case "INCREMENT_AGE":
      return { ...state, age: state.age + 1 };
    case "DECREMENT_AGE":
      return { ...state, age: state.age - 1 };
    default:
      return state;
  }
};

export default function App() {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <div className="App">
      <h3>name: {state.name}</h3>
      <p>occupation: {state.occupation}</p>
      <p>age: {state.age}</p>
      <button onClick={() => dispatch({ type: "INCREMENT_AGE" })}>
        increment age
      </button>
      <button onClick={() => dispatch({ type: "DECREMENT_AGE" })}>
        decrement age
      </button>
    </div>
  );
}

We initialized the state to be an object containing name, occupation and age. The state is rendered onto the screen with two extra buttons to increment and decrement the age. Whenever the user clicks on any one of these buttons, the dispatch will be called with an object as an argument, the object contains a type key with some value.

The dispatch function then invokes the reducer function, which has access both to the state and action( argument's passed to dispatch ). In case of our example, depending upon the type of action that took place, the state varies. If none of the actions matches, the default case will take, which returns the same old state back.

Sometimes, we also send another key named payload along with type to the dispatch's object. In payload, we can send anything to produce the desired results.

A good rule of thumb to when to use the useReducer() hook is "when there are more than three useStates()". This is how we can use and leverage useReducer() hook to our advantage. And before parting ways, one interesting thing is that useContext + useReducer = mini Redux. Now you have your own redux.

 
Share this