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:
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;
This code block will render the core MovieCard
with essential movie data like movie poster
and title
.
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>
);
};
};
The new enhanced version of the movie card component will look like this.
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 />);
The code written above will visually look like this:
Top comments (0)