A detailed introduction to Render Props and Higher-Order Components in React
If you have been doing some React development recently, you must have come across terms like HOCs and Render Props. In this article, we’ll go deep into both these pattern to understand why we need them and how we can correctly use them to build better react applications.
Why do we need these patterns?
React offers a simple method for code reuse and that is Components. A component encapsulates many things ranging from content, styles and business logic. So ideally in a single component we can have a combination of html, css and js all of which have a single purpose, a single responsibility.
Tip: Using Bit (GitHub) you can organize and share reusable components to be discovered, shared and developed from different projects and applications. It’s faster than re-writing them or maintaining a heavy library. Give it a try 🙂
Let’s suppose we are working on an E-commerce application. Like any E-commerce application, a user is shown all the products available, and the user can add any product to cart. We will fetch the products data from an API and show the product catalog as a list of cards.
In this case, the React component can be implemented like this:
For our admins, there is a management portal where they can add or remove products. In this portal we fetch the products data from the same API and show the product catalog in tabular form.
This React component can be implemented like this:
One thing that immediately sticks out is that both the components implement the product’s data fetching logic.
Going forward these situations might arise too.
- We have to use the products data and show it in a different manner.
- Fetch products data from different API (useful in User’s Cart page) but show it just like we do in
- Instead of fetching data from API, we have to access it from localStorage.
- In the tabular product catalog, instead of a delete button, have a button with a different action.
If we make a different component for each of these then we’ll be duplicating a lot of code.
Fetching data and showing data are two separate concerns. As said earlier, It is much better if one component has one responsibility.
Let’s refactor the first component. It will take products data as prop and render the product catalog as a list of cards just like before. Since we don’t need component state and lifecycle methods we’ll convert it to a functional component.
It will look like this now:
ProductTable will be a function component that take product data as prop and render the data as rows of table.
Now let’s make a component named
ProductsData. It fetches the products data from API. The data fetching and state updating will be just like in the original
ProductList component. But what should we put in the render method of this component?
If we simply put the ProductList component then we can’t reuse this component for ProductTable. Somehow, if this component can ask for what to render then the issue will be solved. At one place we will tell it to render the
ProductList component and in the management portal we will tell it to render
This is where render props and HOCs come into play. They are nothing but ways for a component to ask what should it render. This drives code reuse even further.
Now that we know why we need them, let’s see how to use them.
We have a function that calculates the sum of two numbers. At first we just want to log the result to console. So, we designed the function like this:
However, we soon find out that the sum function is very useful and we need it in other places also. So, instead of logging it to console we want the sum function to provide the result only, and let the caller decide how it wants to use the result.
It can be done in this manner:
sum function a callback function as argument
sum function then calculates the result and calls
fn with the result as an argument. This way the callback function gets the result and it is free to do anything with the result.
This forms the essence of render props. We will gain more clarity by using the pattern so let’s apply it to the problem we are facing right now.
Instead of a function that calculates the sum of two numbers, there is a component
ProductsData that fetches products data. Now
ProductsData component can be passed a function via props. The
ProductsData component will then fetch products data and provide that data to the function that was passed as prop. The passed function can now do whatever it want with the products data.
In React, it can be implemented like this:
Just like the
fn argument, we have a render prop which will be passed a function. Then the
ProductData component calls this function with products data as argument.
We can thus use the
ProductData component in this manner.
As we can see render props is quite a versatile pattern. Most things can be accomplished in a very straight-forward manner. And this is exactly why we can shoot ourselves in the foot.
A simple way to avoid nesting is to break out the component into smaller components and keep these components in separate files. Another way is to make more components and compose them instead of having long functions inside render props.
Next we’ll look at another popular pattern called HOC.
Higher Order Components (HOC)
In this pattern we define a function which takes a component as an argument and then returns the same component but with some added functionality.
Understanding HOCs with code is much easier than to explain with words. So we’ll look at the code first.
As we can see the data fetching and state updating logic is just like what we did in render props. The only change is that the component class is inside a function. The function takes a component as argument and then inside the render method of the class we render the passed component but with additional props. Pretty simple implementation for a pattern with such a complicated name, right?
So now we have looked at why we need render props, HOCs and how we can implement both of them.
One question remains: how do we choose between Render Props and HOCs? There have been quite a lot of articles on this topic so I won’t talk about that now. Maybe in my next post 🙂
When to NOT use Render Props — Kent C. Dodds
HOCs vs Render Props — Richard Kotze
In this article we looked at why we need these patterns, the essence of each pattern and how we can leverage these patterns to build highly reusable components. That’s all for now, hope you liked it, and please feel free to comment and ask anything. I’d be happy to talk 👏
October 2018 Update : React hooks has been released in alpha. They will take away the pain of writing Class Components, HOCs and Render Props. I will be writing an explainer soon, follow me on Twitter and Medium or subscribe to my newsletter to get updates on it.