The past week got me learning a lot of things, a lot of concepts I would really love to share. I would begin by discussing Higher-order functions(HOCs) In react.
To be able to understand Higher order components in react, we would first need to understand what Higher Order functions are in JavaScript. Higher-order functions in Javascript are functions that take other functions as arguments and return another function. Examples of the higher-order functions are the; .map
, .filter
, etc. Some of them I wrote about in this article:
.forEach(), .map(), .filter() .... What's the difference?
Johnson Ogwuru ・ May 11 '18 ・ 1 min read
It’s important to note that I’m assuming you have prior knowledge of React if you don’t below is an awesome tutorial by traverse media.
That aside let’s jump right in.
Higher Order Components are components that take as argument another component or components and returns a new component. Could be likened to a Higher Order function, well that’s where the name came from. It is an advanced technique in react for re-using the logic of a component. HOC’s could be used when we want to abstract a login component from the other components in a site, and I would demonstrate how. HOCs are commonly used as advanced react patterns for designing some components that share certain behaviors in a way that makes them connected differently than just the normal state-> props pattern. HOCs as an advanced react pattern allows us the capability of reusing component logic. Think about the functionality of the login component I mentioned. The login could be just a form that takes as value a username, and password and performs a check against a database or any storage means if the user exists on the system. if the user does, and the password entered is correct, then the App component would render the content component, but if the user doesn’t exist, the App renders the login component, the same could be applied to when checking if a user on the site still has a valid authentication. This example could be performed using a Higher-order component. But how, the code below demonstrates how.
Say we have an App component as such
import React, { Component } from 'react'
//below is the app component that would render to the DOM
export default class App extends Component {
render() {
return (
<div>
<h1> Hello world </h1>
</div>
)
}
}
To create a higher order component that would perform the function we want, which is determining which component to render depending on the status of the user's login session, we would first have to create the two components.
Please note, to make this explanation as simple as it could possibly get, I would be creating all of the components inside the app.js file. And also we would be making use of create-react-app, please get it set up
Below, we would be creating both the login and content components, both are actually going to be dummy components simply calling out their names in an h1
tag.
import React, { Component } from 'react'
// Login Component
export default function Login {
return (
<div>
<h1>Hi i'm login</h1>
</div>
)
}
//Content component
export default function Content {
return (
<div>
<h1>Hi i'm Content</h1>
</div>
)
}
//App component
export default class App extends Component {
render() {
return (
<div>
//Add component to render here
</div>
)
}
}
Having built out the individual components, it's time for us to create our HOC.
Please note that you can choose to create this in a different file, but to make this article simple and straight to the point, I would be doing everything from a single file.
Copy and paste the following code immediately under the Content
component and before the App
component.
const withAuthentication = Component1 => Component2 =>
class extends Component {
constructor(props) {
super(props);
this.state = {
isLoggedin: false,
};
}
render(){
if(this.state.isLoggedin) {
return <Component1 />
} else {
return <Component2 />
}
}
The above is as simple as a Higher-order Component can be.
It's of vital importance that we note how
HOCs
are named, it's generally accepted that they are named starting withwith
and then whatever their specific job is, In our case authentication. That way anyone looking at your code knows it's a Higher-order component without looking at the code, this is especially very important where theHOC
leaves in a separate file.
To explain the code. We use what is being referred to as curring
in JavaScript to receive the arguments supplied to a HOC
. Currying was what we did when we passed the two arguments to the HOC
as so; Component1 => Component2 =>
, which is actually equivalent to us declaring a method and passing an argument to it, the normal Javascript way.
Further down, the HOC returns an anonymous class which has a state object, that houses the isLoggedin
property, which you would manipulate however you want, during the course of developing your application, to determine when a user is logged in and when they are not.
Further down to the render()
method, we add a condition to check the state for the value of isLoggedin
, so whatever the value is a Component is being returned respectively.
Now, the question in your mind could obviously be how you can get to use this. Pay close attention. Copy and paste the following code immediately under the HOC withAuthentication()
we just wrote.
const DoAuthenticate = withAuthentication(Content, Login);
Now by assigning our HOC withAuthenticate
to a function DoAuthenticate
, we are setting whatever the returned function inside of HOC to DoAuthenticate
who from how it's named, shows it's a component.
Because of how our HOC was organized, we need to make sure the
Content
component stays at the position ofComponent1
in theHOC
because we expect it to be returned when the user is logged and theLogin
component taking the position ofComponent2
as defined in theHOC
.
Now instead of having to wonder which Component to render to the DOM
through the App Component, we just render the DoAuthenticate
and allow the HOC
do the pondering over for us. In the end, our code should look like so.
import React, { Component } from 'react'
// Login Component
export default function Login {
return (
<div>
<h1>Hi i'm login</h1>
</div>
)
}
//Content component
export default function Content {
return (
<div>
<h1>Hi i'm Content</h1>
</div>
)
}
// Higher order Component
const withAuthentication = Component1 => Component2 =>
class extends Component {
constructor(props) {
super(props);
this.state = {
isLoggedin: false,
};
}
render(){
if(this.state.isLoggedin) {
return <Component1 />
} else {
return <Component2 />
}
}
const DoAuthenticate = withAuthentication(Content, Login);
//App component
export default class App extends Component {
render() {
return (
<div>
<DoAuthenticate />
</div>
)
}
}
Learning about HOCs was really fun for me and I made two applications during the week, to deepen my understanding of it. Here are links to the applications.
Instaclone a clone of the Instagram application(not a complete clone though...lol) and LambdaTimeX. Would be dropping links to they Repos on the comment section.
To further your knowledge, I would recommend you give this article on HOCs by Sitepen a shot. 🥂🥂🥂🥂
Top comments (9)
I use HOC to separate logic from view.
Imagine you have component that allows users to select an item from a list.
I'd split it like this:
Functional component which is used to render the component.
Class component which holds logic/state for that component.
SelectLogic is a HOC for SelectView. Of course both components are replaceable, so you can switch Login/View depending on the needs.
That's okay too
I just can't understand HOC. We can use custom components for reusable code and logic, can't we?
Sorry for the late response. Yes, but most times I actually use HOCs for determining which components should be rendered. Like choosing when to render a login component or an error page component
Just spend last few days with HOC and I understand your point now. Thank you John
I'm happy you understand it now.. Cheers
Hello i'm new in this topic, and I thinking if is there any difference from doing like this example or just literally importing 2 components inside my main component and render conditionally one or another.
@johnson Nicely explained the HOC Functions & components. Another doubt how to publish this types of HOC into npm .
If I get what you mean, I haven't really given it a shot, so I can't say