DEV Community

Cover image for Higher Order Component
Jorjis Hasan
Jorjis Hasan

Posted on • Updated on

Higher Order Component

Higher Order component is a function that takes a component and returns a component. At the end of the day it's just a normal function.

  • Why do we use it ?
  • When do we use it ?
  • What component does it take ?
  • What component does it returns ?

Let me tell you the theory behind it. So, a higher-order component takes a component as input, enhances that component, adds some extra features to the component, and returns it. Still don't make any sense? Okay, I'm holding your hand and walking you through by example.

Example: From my movie list, I want to add a New ๐ŸŒฑ label to specific movie cards. Does it sound exciting?
Here is the live link and source code.

Visual Picture:

a screenshot from app


Step 1:

First, we need to make a basic utility movie card. After that we'll add features to that component.

//MovieCard.js

import { mediaUrl } from "./constants";

const MovieCard = ({ info }) => {
  const { id, backdrop_path, original_title } = info;

  return (
    <div className="rounded-lg overflow-hidden drop-shadow-md max-w-[400px] border-[1px] border-gray-400">
      <img key={id} src={mediaUrl + backdrop_path} />
      <div className="bg-w font-sans py-4 text-center font-semibold font-xl">
        {original_title}
      </div>
    </div>
  );
};

export default MovieCard;
Enter fullscreen mode Exit fullscreen mode

This code block will render the core MovieCard with essential movie data like movie poster and title.

Movie Card

Step 2:
Now, without touching/modifying the core MovieCard code, let's create a version of MovieCard by adding the New label.

// WithNewLabel (higher-order-component)
export const WithNewLabel = (MovieCard) => {
  return (props) => {
    return (
      <div>
        <label className="absolute z-10 bg-blue-600 text-white rounded-lg py-2 px-4">
          New ๐ŸŒฑ
        </label>
        <MovieCard {...props} />
      </div>
    );
  };
};
Enter fullscreen mode Exit fullscreen mode

The new enhanced version of the movie card component will look like this.

solo screenshot

For the sake of a higher-order component, it's easy to add/remove variable features like 'popular,' 'new,' or 'trending', anything that fits our needs.

Rendering On Condition:

We are done making components MovieCard and WithNewLabel as higher-order components. It's time to see the use cases in action.

import React from "react";
import ReactDOM from "react-dom/client";
import MovieCard, { WithNewLabel } from "./MovieCard";

const movieList = [
  {
    backdrop_path: "/6Xfj8wD7GoEysgcFayRKd6QLqai.jpg",
    id: 843527,
    original_title: "The Idea of You",
    release_year: 2024,
    release_month: 5,
  },
  {
    backdrop_path: "/nb3xI8XI3w4pMVZ38VijbsyBqP4.jpg",
    id: 872585,
    original_title: "Oppenheimer",
    release_year: 2023,
    release_month: 7,
  },
];

const isNewMovie = ({ release_year, release_month }) => {
  return release_year === 2024 && release_month > 2 ? true : false;
};

const Body = () => {
  <div className="flex flex-wrap flex-row gap-[16px] justify-evenly">
    {movieList.map((movie) => {
      const NewLabel = WithNewLabel(MovieCard);

      if (isNewMovie(movie)) {
        return <NewLabel key={movie.id} info={movie} />;
      } else {
        return <MovieCard key={movie.id} info={movie} />;
      }
    })}
  </div>;
};

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<Body />);
Enter fullscreen mode Exit fullscreen mode

The code written above will visually look like this:

Visual Illustration

Top comments (0)