React.js Explained: Comparing and Converting Higher-Order Components to Hooks with Practical Examples
Tags: javascript, react, programming, webdev
Published: 2023-06-01 18:12:24

This article simplifies the complex concept of Higher-Order Components (HOCs) and Hooks in React, highlighting their differences with clear code examples.

## **Target Audience**

If you're a React developer looking to elevate your understanding of Higher-Order Components (HOCs) and Hooks, or if you're just embarking on your React.js journey, this enriching guide is tailored for you. We're about to delve into these critical concepts with ample real-world examples and engaging code samples that will help you grasp their practical applications.

## **Learning Objectives**

At the end of this article, you should be able to do the following:

1. Identify Higher-Order Components in your React application.
    
2. Craft and deploy Higher-Order Components effectively.
    
3. Leverage React Hooks as an alternative to HOCs.
    

So, brace yourself for this exciting adventure!

## **Introduction**

While exploring React.js for professional development, I discovered a valuable resource: an E-book about React patterns. This book teaches the different patterns used in React, explaining their importance in the tech industry. One concept I found interesting was the Higher-Order Component, which operates similarly to a higher-order function in JavaScript.

## **Diving into Higher-Order Components**

Have you ever wondered about the Higher-Order Function concept in JavaScript? If so, you'll find the Higher-Order Component (HOC) concept in React.js fascinating!

In layman's terms, a Higher-Order Component (HOC) is a function that graciously accepts another component as an input and spits out a brand new, more capable component. The strength of HOCs lies in their ability to minimize code repetition, keeping your codebase lean and mean.

To illustrate, consider an e-commerce app with various components needing the same API calls. Alternatively, visualize multiple components that demand identical business logic, say, user authentication. Here, HOCs strut in as a superhero, eliminating the repetition and keeping your code DRY (Don't Repeat Yourself).

Let's dive into a concrete example. We'll use the popular Pokémon API to showcase an HOC in action.

```javascript
import React from "react";

const withData = (Component) => {
  class WithData extends React.Component {
    state = {result: []};

    componentDidMount() {
      this.fetchData();
    }

    fetchData = async () => {
      const response = await fetch("https://pokeapi.co/api/v2/pokemon");
      const data = await response.json();
      this.setState({result: data.results});
    };

    render() {
      return <Component results={this.state.result} />;
    }
  }

  return WithData;
};

export default withData;
```

The `withData` function defined above is our hero HOC. It accepts a component and makes an API call to fetch Pokémon data. The fetched data is then added to the local state and passed as a prop to the child component.

Let's see `withData` in action:

```javascript
import withData from "./withData";

const ListResults = ({ results }) => (
  <ul>
    {results.map((pokemon) => (
      <li key={pokemon.name}>{pokemon.name}</li>
    ))}
  </ul>
);

export default withData(ListResults);
```

Our `ListResults` component receives the fetched Pokémon list from `withData` and renders it beautifully on the screen. No sweat!

## **Adventures with React Hooks**

React Hooks enable function components to harness React's state and lifecycle features without having to convert to class components, making your code more readable and manageable.

Let's reimagine our previous example using Hooks this time:

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

const useData = () => {
  const [results, setResults] = useState([]);

  const fetchData = async () => {
    const response = await fetch("https://pokeapi.co/api/v2/pokemon");
    const data = await response.json();
    setResults(data.results);
  };

  useEffect(() => {
    fetchData();
  }, []);

  return results;
};

export default useData;
```

The `useData` Hook functions just like the `withData` HOC. It fetches Pokémon data and stores it locally using the `useState` Hook. The `useEffect` Hook ensures the data fetch occurs when the component mounts.

Let's couple this Hook with our `ListResults` component:

```javascript
import useData from "./useData";

const ListResults = () => {
  const results = useData();

  return (
    <ul>
      {results.map((pokemon) => (
        <li key={pokemon.name}>{pokemon.name}</li>
      ))}
    </ul>
  );
};

export default ListResults;
```

Notice how clean and straightforward this is? `ListResults` calls `useData`, which returns the fetched data. Contrary to HOCs, Hooks don't pass data via props, leading to simpler code.

React Hooks have quickly become a developer's favorite, thanks to their simplicity, readability, and testability. They facilitate separation of concerns, resulting in a cleaner and more maintainable codebase.

## **Wrapping Up**

We've delved into the world of Higher-Order Components and Hooks, explored their differences, and seen them in action through real-world examples. Armed with this knowledge, you're now empowered to identify, create, and implement both HOCs and Hooks in your React applications. Plus, you're equipped to convert an HOC into a Hook in your React projects, bringing simplicity and elegance to your code.

Let's continue creating extraordinary applications with React!