React Hooks: useReducer

React Hooks: useReducer

The Blog Post, React Hooks: useState is a prerquisite for this blog lesson

What is a React Hook?

A React hook is a function that allows us to use React features in our functional components. They are especially useful because they enable functional components to have stateful logic, side effects and access to react features without needing class components. Knowing React hooks is essential for building modern React applications efficiently and effectively since they provide those powerful tools for managing state like we discussed.

Okay so what exactly is stateful logic?

When we talk about stateful logic, we are essentially referring to the behaviour of functionality in a program that relies on the current state of the application or component. (The word state implies that there are elements of the component that can change and the "state" is the current condition of those elements that have the ability to change). It involves managing and updating data based on changes in state.

Changes in state include:

  • UI interactions

  • Updating Data

  • API Responses

  • Other external factors

Why use react hooks ?

There are a bunch of advantages to using react hooks including for example: They are incredibly simple and most of all reusability. They reduce the need for class components and lifecycle methods. This makes code more concise and easier to understandm promoting reusability accross components.

Now that we have a fundamental idea of what we are working with, let's get busy with hooks !

At this point, we understand that the state of our components are managed using the useState hook. As you can imagine, a functional component's state becomes a lot more complex as the application itself becomes more complex. This complexity comes about in various ways. One of the most common occurances is that we need to manage several variables containing stateful data.

How exactly does useReducer Address this problem?

The useReducer hook allows us to encapsulate all our stateful data into a single management system. When we discussed the useState hook, we mentioned how it uses a function to deploy actions that update the stateful data. When we have various stateful data to manage, we would end up having a cluster of functions. With the use reducer function, we encapsulate all these actions.

  • useReducer()

The useReducer function receives two arguments. A single required argument and an optional argument:

  1. Reducer Function (required) - the function that is going to handle all the changes in our stateful data.

  2. The initial value of our stateful data (optional)

  • const [variable, dispatch] = useReducer(Reducer, variable)

Just like the useState Hook, the useReducer function returns an array containing the initial value of the stateful data.

Note: In this case, we are using a single function to represent all the instanes of stateful data in our functional component.

Now, remember that all our actions are stored in a single function. This means that our function is segmented into different segments for each individual action. So when we destructure the array, we will declare the particular segment of the function that addresses the current stateful data.

These segments are created using switch cases inside of our reducer function. This reducer function recieves two arguments. The state and the action

Each case in the switch statement is an action mapped to a unique dispatch. When a dispatch is passed to the function, the corresponding action is executed. Each trigger in the component is mapped to a variable containing a unique dispatch.

import React, { useReducer } from 'react';

// Reducer function
const reducer = (state, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return { count: state.count + 1 };
    case 'DECREMENT':
      return { count: state.count - 1 };
    default:
      return state;
  }
};

function Counter() {
  // Initial state and dispatch function
  const [state, dispatch] = useReducer(reducer, { count: 0 });

  return (
    <div>
      <p>Count: {state.count}</p>
      <button onClick={() => dispatch({ type: 'INCREMENT' })}>Increment</button>
      <button onClick={() => dispatch({ type: 'DECREMENT' })}>Decrement</button>
    </div>
  );
}

export default Counter;