Reusing React Component logic with Higher Order Component
A Higher Order Component is a great pattern that has proven to be very valuable. React emphasizes composition over inheritance, making it easy to compose larger components by reusing smaller ones.
In this post we will review in detail how to employ Higher Order Components in code reuse and logic abstraction.
What are Higher Order Components?
Higher Order Component is a function that takes a component and returns a new component.
This pattern is usually implemented as a function, which is basically a class factory.
React uses Higher Order Components (HOCs) as an alternative to inheritance. Similar to Higher Order functions, which take or return other functions
const EnhancedComponent = higherOrderComponent(wrappedComponent)
if you have used react-redux, you have probably already used at least one Higher Order Component. One of its primary functions is CONECT which accepts a component and returns a component connected to the Redux store, wrapping the one provided. It saves you the hassle of managing the logic connection to the store in multiple places in your app.
What can I do with HOCs?
HOCs can be used for
- Code reuse and logic abstraction
- Props manipulation
- State abstraction and manipulation
- Render Highjacking
In this article we will focus on code reuse and how we can use Higher Order Components as an alternative to inheritance
The Problem
Let’s say you have an onClick and onChange event handlers accessing state, and you plan to utilize this event handler in a bunch of different components. You could of course create a lot of duplicated code. Remember the rule, don’t repeat yourself (DRY).
Imagine you have a SigIn and a SignUp component
SignIn Component
Sign Up Component
You will notice something predominant about these two components — there is a repetition of code. If we want to inject the onClick event handler and the onChange event handlers into arbitrary components without redundancy, an HOC is perfect.
Creating a Higher Order Component
Before creating a Higher Order Component we will have to break our components into Container and Presentational components
In this world, components can be classified into those that access the global state, and those that don’t.
Container component: container components have direct access to the global state i.e connected to the redux store. They also provide the data and behavior to presentational or other container components. They are often stateful, as they tend to serve as data sources.
Presentational Component: these are also called functional components. They rarely have their own state, but when they do, it’s a UI state rather than data. They are written as functional components unless they need state, lifecycle hooks, or performance optimizations.
That said lets go back to restructuring our components. The first thing we are going to do is to convert our “sign in” and “sign up” components into functional and stateless component
SignIn Component
SignUp Component
showSignin and showSignup when clicked toggles between the signin and the signup component.
Now that we have refactored our component the next thing we are going to do is to create a Higher Order Component
Higher Order Component(HOC)
The important part here is that the render method returns a React Element of type WrappedComponent. We also pass down the props the HOC receives.
It should be noted that in this example, we passed all props from our authenticate HOC to the wrapped component using the spread operator. This is typically advisable, as it allows the HOC to be used in place of the wrapped component.
The next thing we are going to do is to place the signin and the signup component in a single component. This component will be called Index.jsx and will serve as a container component for the two components.
Index Component
Here we have abstracted all our logic into the HOC and are passing it down to the wrapped component which is our SignIn and SignUp components. We create a Higher Order Component by just passing in a component to wrap.
const EnhancedComponent = higherOrderComponent(wrappedComponent)
This can now be used anywhere wrappedComponent was used previously, as it returned a component wrapping wrappedComponent.
Keep in mind , in most of cases HOC will return something that looks like an original component. To achieve this you often have to pass HOC propTypes and the rest of static methods, which may exist in original Component.
You can find more information about this at the end of Facebook`s article.
Conclusion
HOC is awesome, they are at heart a codification of a separation of concerns in components in a functional way.
I hope that after reading this post you are a bit more knowledgeable about React HOCs. They are highly expressive and have proven to be pretty useful in different libraries.