The Transition From Higher-Order Component Pattern to React Hooks Pattern
Tags: react, webdev, javascript, tutorial
Published: 2022-03-11 09:33:32

_by author [Tapas Adhikary](https://blog.openreplay.com/authors/tapas-adhikary)_

Reusability is an essential principle to follow in software development and programming. React(also known as React.js or ReactJS) is a component-based declarative user interface library that provides us with a solid ground to adhere to it. React's Higher-Order Component(HOC) Pattern is a great way to achieve it.

In this article, we will learn about the `Higher-Order Component` pattern and then transition to understanding the `React Hooks` pattern with lots of examples. [Please read this article](https://blog.openreplay.com/understanding-the-container-component-pattern-with-react-hooks) if you are new to React or look forward to understanding how the `Container Component` Pattern works.


## The Higher-Order Component(HOC) Pattern
The `Higher-Order Component` is a pattern to extend and reuse an existing component. You do not want to duplicate code logic across components. It is extra work and causes adverse situations like bugs maintenance issues. Also, you may want to enhance a component and use it for a completely different purpose.

As defined in React's [official documentation](https://reactjs.org/docs/higher-order-components.html),

> A higher-order component is a function that takes a component and returns a new component.

So, you can visualize the usage of HOC as,

```javascript
const EnhancedComponent = HOC(WrappedComponent);
```
Here the `HOC` is the higher-order component that takes `WrappedComponent` and returns a new `EnhancedComponent`. Now let's learn more about HOC with examples.

Let's consider a couple of React components to list down movies from a database and show analytics about those movies, respectively.

- `MovieListWithHOC`: A component that lists down the movie information like name, cover image, director name, and so on.
- `MovieAnalyticsWithHOC`: A component that shows the analytics on the movie data.

These components have a standard requirement, i.e., fetching the data from the database. Let's assume we have an API(URI: https://json-faker.onrender.com/movies) that we can request to fetch the movie data as a response.

The logic of fetching the movie data using the API is a common need for both components. But wait, we don't want to repeat the data fetching logic in both components. Instead, we will use the HOC pattern to reuse the fetching logic and enhance the components.

First, let us create a HOC with the movie data fetching logic.

```javascript
import React from "react";

// Craete a HOC that takes a component as an argument
const withFetch = (WrappedComponent) => {
    
  // Create a Class Component that will
  // enhance the WrappedComponent 
  class WithFetch extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        movies: [],
      };
    }

    componentDidMount() {
      // Fetch the movie data by making an API call  
      fetch("https://json-faker.onrender.com/movies")
        .then((response) => response.json())
        .then((data) => {
          this.setState({ movies: data.movies });
        });
    }

    render() {
      return (
        <>
          {this.state.movies.length > 0 && (
            <WrappedComponent movies={this.state.movies} />
          )}
        </>
      );
    }
  };
  
  // It is optional to set the display name of the
  // component but useful when comes to debug the HOC.
  WithFetch.displayName = `WithFetch(${WithFetch.name})`;
  
  // Finally, return the component
  return WithFetch;
};

export default withFetch;
```

A few things to note here:
- We have created a Rect component(A regular JavaScript function) `withFetch` that takes a component(WrappedComponent) as an argument.
- The `withFetch` component returns a component(Class component).
- We create a state variable called `movies` and update it using the response of the API call in the `componentDidMount` lifecycle method.
- Now take a look into the JSX part of the component. Here we enhance the `WrappedComponent` passing the movies data as props.
- Finally, we return the component(Class Component). The core part of this component is the WrappedComponent enhanced with the movie data.

It is powerful because now you can pass a presentational component(people call it a dumb component!) to the `withFetch` Higher-Order component to get back a fully operational component with data. The best part is several presentational components(say, one to list movies and another to show analytics), which can use the same HOC to fetch data and represent them differently. Isn't that amazing?

Let's use the HOC to create a movie listing component,

```javascript
import MovieContainer from "../movies/MovieContainer";
import "../movies/movies.css";
import withFetch from "./MovieWrapper";

const MovieListWithHOC = (props) => {
  const { movies } = props;
  return (
    <div className="movie-container">
      <h2>Movie List - With HoC</h2>
      <MovieContainer data={movies} />
    </div>
  );
};

export default withFetch(MovieListWithHOC);
```

As the code above shows, the `MovieListWithHOC` is a presentational component enhanced with the HOC(withFetch).

Please note the export, it says,

```javascript
export default withFetch(MovieListWithHOC);
```
So, the `MovieListWithHOC` component gets the movie data as props and pass it to another component called `MovieContainer` to render the data. You can take a look into an example implementation of the MovieContainer component [from here](https://github.com/atapas/react-play/blob/release/openreplay-hoc-hooks/src/movies/MovieContainer.js).

Similarly, we can have another component for showing movie analytics using the same movie data,

```javascript
import MovieAnalytics from "../movies/MovieAnalytics";
import "../movies/movies.css";
import withFetch from "./MovieWrapper";

const MovieAnalyticsWithHOC = (props) => {
  const { movies } = props;
  return (
    <div className="movie-container">
      <h2>Movie Analytics - With HoC</h2>
      <MovieAnalytics data={movies} />
    </div>
  );
};

export default withFetch(MovieAnalyticsWithHOC);
```
You can take a look into an example implementation of the MovieAnalytics component [from here](https://github.com/atapas/react-play/blob/release/openreplay-hoc-hooks/src/movies/MovieAnalytics.js).

I hope you found the usage of HOC impressive. It is an excellent use of code reusability. Many React-based libraries (including React) like Redux, React-Router use this pattern. 

Before we move to the next section to understand the React Hook patterns, please be aware of [a few Caveats](https://reactjs.org/docs/higher-order-components.html#caveats) mentioned in the React documentation.

## Open Source Session Replay
Debugging a web application in production may be challenging and time-consuming. [OpenReplay](https://github.com/openreplay/openreplay) is an Open-source alternative to FullStory, LogRocket and Hotjar. It allows you to monitor and replay everything your users do and shows how your app behaves for every issue.
It’s like having your browser’s inspector open while looking over your user’s shoulder.
OpenReplay is the only open-source alternative currently available.

![OpenReplay](https://raw.githubusercontent.com/openreplay/openreplay/main/static/replayer.png)

Happy debugging, for modern frontend teams - [Start monitoring your web app for free](https://github.com/openreplay/openreplay).



## The React Hooks pattern
`React Hooks` are a new inclusion to the library in version 16.8. Before that,  we couldn't use the state and a few other React features outside the class-based components. In React, we can create a component using JavaScript classes or functions. With the advent of Hooks, now it is much easier to embrace functional programming in React.

With functional components and hooks together, we can separate the concern of managing state and side-effects from a component to a hook. The hook can isolate all these components' plumbing works to keep it `pure`. 

React provides various standard hooks out-of-the-box. The `useState`, `useEffect`, `useMemo`, `useCallback`, `useRef`, are a few to name. We can also create custom hooks to separate the reusable logic and possible side-effects from a component. If you are new to React Hooks, [here is a short video](https://youtu.be/CvNvRaS3u60) to give you the fundamentals of React Hooks.

Alright, we have learned that HOC helps in reusability, and so does the React Hook. So can we convert a HOC to a React Hook and use that instead? That way, we will be fully "functional", right? Yes, let's do that.

It is a convention to name a React Hook starting with `use`(yes, the letter u is in the smaller case!). Let us create a custom hook called `useFetch`.

```javascript
import { useState, useEffect } from "react";

const useFetch = (url) => {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const fetchData = async () => {
      const response = await fetch(url);
      const json = await response.json();
      setData(json);
      setLoading(false);
    };
    fetchData();
  }, [url]);

  return [loading, data];
};

export { useFetch };
```

Let's understand the code above step-by-step:

The `useFetch` hook is a JavaScript function that takes an URL as an argument. It is the API URL to fetch data. The hook is very flexible to fetch data using any API URL passed. We will pass the API URL to fetch the movie data in our case.

The hook uses two state variables, `loading` and `data`. The state variables are declared and tracked for changes using the `useState` hook.

> **useState**: It helps manage the local state so that React can preserve and use the state between re-renders. The useState hook returns the current state value and a function to update the state value. We can also pass the initial state value to the useState() hook.

Next, the `useEffect` hook manages the side-effects of making the API call and fetching the data. Once complete, we update the state variables indicating the data loading is done and fetched.

> **useEffect**: The useEffect hook helps in performing side-effects. The side-effect can be anything responsible for changing the state of your application. A typical example of a side-effect is making an API call and changing the local state to preserve the response data.

Finally, we return both the state variables in an array.

Great, not it's the time to use the hook in a component to get the movie data and render in the UI. How about we use it for the same `MovieAnalytics` component we have used before?

Let's create a component called `MovieAnalyticsWithHook` to demonstrate it,

```javascript
import { useFetch } from "../hooks/useFetch";
import MovieAnalytics from "../movies/MovieAnalytics";

const MovieAnalyticsWithHook = () => {
  const MOVIE_URI = "https://json-faker.onrender.com/movies";
  const [loading, data] = useFetch(MOVIE_URI);
  return (
    <div>
      <h1>Movie Analytics with Hooks</h1>
      {
          loading ? 
          <h2>Loading...</h2> : 
          <MovieAnalytics data={data.movies} />
      }
    </div>
  );
};

export default MovieAnalyticsWithHook;
```
We call the `useFetch` hook passing the movie API URI in the code above. It returns the `loading` and `data` values that we destructure into two variables.

```javascript
const [loading, data] = useFetch(MOVIE_URI);
```

Next, in the JSX part, we use `loading` and `data` to show the movie analytics.

That's it. I hope you enjoyed learning about the Reach Hooks as well. You can find all the source code used in this article from here,

> [The HOC and Hooks Project on GitHub](https://github.com/atapas/react-play/tree/release/openreplay-hoc-hooks/src)

## In Summary
To Summarize,

- The Higher-Order Component(HOC) Pattern is a popular React pattern to empower reusability among components.
- HOC is a function that takes a component as an argument and returns an enhanced version.
- HOC helps to isolate logic and state management in a separate class-based component.
- With React Hooks, state management can occur outside of a class.
- Hooks empower developers to use the functional programming aspects in React.
- There are standard hooks, and we can write custom hooks.
- Hooks are helpful to isolate the state and side-effects from a component and encourage reusability.
- The React developer community aggressively adopts React Hooks over Higher-Order Components for a new implementation.


## Before we end…
I hope you found this article insightful and informative. After spending many years with ReactJS, I have started a [YouTube Video Series](https://www.youtube.com/watch?v=ODKIxaSMgpU&list=PLIJrr73KDmRyrDnDFy-hHvQ24rRjz6e_J) that aims to cover all the aspects of React.js end to end. Please [SUBSCRIBE](https://www.youtube.com/tapasadhikary?sub_confirmation=1) if you find it helpful.

Let's connect. I share my learnings on JavaScript, Web Development, and Blogging on these platforms as well:

- [Follow me on Twitter](https://twitter.com/tapasadhikary)
- [Side projects on GitHub](https://github.com/atapas)
- [React.JS Community on Showwcase](https://www.showwcase.com/community/react.js)