The What, Why and How of React (High Order Components)
miguel-penaloza
Posted on July 19, 2018
Hi, in these series of articles I will talk about React concepts, try to explain what exactly means that concepts, why you could need it and how use it, in this post we're going to talk about the High Order Components (HOC). In simple words is a pattern to create logic that could be easily reused for other components, and you will see why for the HOCs you need to learn it to understand that you always needed it.
What is a High Order Component?
If we go to the React documentation, there says something like this: is a function that takes a component and returns a new component.. With that definition you maybe can think. why don’t create a class and just extended it? we can have core logic that can be reused in a parent class and extended for all his children yes, but the advantage of use a HOC is that the object of this pattern is return a Component, a simple transaction, I give you my component and the HOC returns a improved new Component with the logic that I need.
So, we can say that a HOC is function, that receive a series of data, properties and a component, include his logic, a context or something else and return a new Component with that logic included, with this pattern you can also be sure that what you need to provide to your component is centralized in one place, and will be consumed always in the same way, like this example:
import React, { Component } from ’react’;
//Create your child component
const ChildComponent = (props) => (<div> Hello Folks<div>);
// Create your HOC
const higherOrderComponent = (ChildComponent) => {
return class extends Component {
render() {
return (<ChildComponent props={}/>);
}
}
}
// Then You send your ChildComponent and receive a new one with some new props provided for the HOC
const newEnhancedComponent = higherOrderComponent(ChildComponent);
As you can see, the sky's the limit for what you can send or provide in your HOC.
Why should I use this?
When you’re building your components, you should always try to create the most simple components as you can with with the least possible responsibility, but sometimes you find yourself with a big component, with a lot of things, and worst, with a lot of logic that you see is redundant. When you see that you need apply some patterns that will make your code more scalable and reusable, so the first reason is a big component doing a lot of stuffs.
The second and more important reason is when you see that a lot of components (more than one can be a lot sometimes) will use some base logic. These 2 will the perfect reasons for you to try to apply this pattern in your proyect.
How should I use?
In the HOC you can add, edit or even remove some props that you will use in your Child or Enhance Component. You can include a context, or even make a call, subscribe to a service, resolve a promise and handle the response in the HOC, instead of make a dispatch in each componendDidMount and have a lot of repeated code. I will give you a list of the most common examples on where and how we can use this pattern with problems and real-life scenarios.
- You already use one, when you use the “connect” of react-redux. If you use redux to hanlde the state and dispatch actions in your code, you're alredy using a HOC, the connect is a HOC that receive your childComponent and your state mappers, and return you a ConnectedComponent. The connect not only gives you the dispatch but also gives you the props and notifies you if these change.
export const mapStateToProps = (state) => ({
information: state.information
});
export default connect(mapStateToProps)(ChildComponent);
- When you need to include an UI component or behaviour to your Child Component. Let's say that you have a component, and you need to include an alert (This can be a modal, change a color, open a hidden text or whatever). And you need that all your components include this extra UI thing. You can just have a HOC that keep the two things together, but each one will be independent with his own responsibilities, like this:
import React, { Component, Fragment } from ’react’;
//Create your child components
const HelloComponent = (props) => (<div> Hello Folks<div>);
const GoodBayComponent = (props) => (<div> And Goodbay<div>);
const AlertComponent = (props) => (<div> I’m an alert <div>);
// Create your HOC
const componentWithAlert = (ChildComponent) => {
return class extends Component {
render() {
return (
<Fragment>
<AlertComponent />
<ChildComponent props={}/>
</Fragment>
);
}
}
}
const HelloWithAlert = componentWithAlert(<HelloComponent />);
const GoodbayWithAlert = componentWithAlert(<GoodbayComponent />);
As you can see here, we have 2 independent components in one, you also can see that I use Fragment instead of a normal div, but Fragment don’t include you any extra markup or element, and let you group without problems and I prefer that.
- When you have a context. Let's say that we have an important information, like the theme with all the brandings, the i18n resources or any kind of information, that you need to provide to all your components. Is very important always try to keep your information in only one source, each component should not be the one of charge of determinate which color or translation based on the language or theme should be used, to handle this situations you need a Context
The Context in React is an API that allow you pass data through the component tree without having to pass props down manually at every level, this’s something very good and useful when we need to handle this kind of problems. The Context needs a Provider and a Consumer, The Provider will have the relevant information and you will need all your childs components wrapped inside the Consumer, so, therefore is a perfect example of where do you need a HOC, you need one to include the theme consumer context logic in the component regardless of which component is, so you don't need to call the ThemeContext everytime you use the component.
import React, { Component } from ’react’;
const ThemeContext = React.createContext({});
class ThemeProvider extends Component {
render() {
const {theme } = this.props;
return (
<ThemeContext.Provider
value={theme}
>
{Children.only(this.props.children)}
</ThemeContext.Provider>
);
}
}
const withTheme = (ChildComponent) => {
return class extends Component {
render() {
return (
<ThemeContext.Consumer>
{
theme =>
<ChildComponent
theme={theme}
{props}
/>
}
</ThemeContext.Consumer>
);
}
}
}
I will talk more about context in a next post because what is really importanttoday is the HOC. Now you have an example of how a HOC can help you with different problems. And I hope that this blog will help you to better understand this concept and that your code will be better and better. Hope you enjoy. See you in the next post!
InTheCodeWeTrust
Posted on July 19, 2018
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 18, 2024