When you pass a component to a function and it returns a new component, it’s called a higher-order component (HOC). If that sounds simple, it is! And your code will be simpler for using them.
Over the course of this post, you’ll see how the higher-order component abstraction will enable your work to be more readable, reusable, and composable.
Before we move forward, let’s define what it is we’re creating a higher-order version of. While you might see these definitions used interchangeably, it’s important to be aware of their differences:
Say we’re about to start work on our app’s user page. We know what our User object looks like, but we haven’t quite decided what kind of authorization we’d like to use. How can we avoid some heartache later when we determine the right way to go? How do we anticipate the possibility of changing our minds in three months when the page is already finished?
We can start with a simple HOC function named withUser
. We want this function to wrap around any component we pass to it and provide our User object as a prop.
const withUser = WrappedComponent => {
class WithUser extends React.Component {
constructor(props) {
super(props);
this.state = {
user: sessionStorage.getItem("user")
};
}
render() {
return <^>{...this.props} />;
}
}
return WithUser;
};<^>
Explained:
withUser
, takes any component as an argument.WithUser
Component class that reads the User object from sessionStorage
and adds it to state.WrappedComponent
as a new element with a user prop from state.this.props
to the inner WrappedComponent
.Alternatively, if state is unnecessary, it’s recommended to use a functional HOC:
const withUser = WrappedComponent => {
const user = sessionStorage.getItem("user");
return props => ;
};
When we want to access the User object on our page, we can call withUser
to wrap the page’s component:
const UserPage = props => (
<div class="user-container">
<p>My name is {props.user}!</p>
</div>
);
export default withUser(UserPage);
And that does it! Our withUser
function takes a component as an argument and returns a higher order component. Three months from now, if we decide to change things around, we only have to edit our HOC.
If you weren’t familiar with HOCs before, you might have encountered them without realizing it! Some notable examples:
connect(mapStateToProps, mapDispatchToProps)(UserPage)
withRouter(UserPage)
withStyles(styles)(UserPage)
The compose
function from redux allows multiple HOCs to be composed into one. For example:
import { compose } from 'redux';
// ... other imports
export default compose(
withStyles(styles),
withRouter,
withUser
)(UserPage);
In this case, our styles, router, and user would all be passed to our UserPage
component.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
Sign up for Infrastructure as a Newsletter.
Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.