Almost everything about using a SPA library influences you to abstract the business logic and write quality code. React has been enforcing such quality controls for the last few years using a variety of amazing design patterns and we are no strangers to that!
In this article, we'll discuss one such addition to the quality control mechanism of React using Higher Order Components. By the end of this article, you should be confident and ready to tackle/improve a codebase by using this principle whenever necessary.
What is a Higher Order Component?
Higher Order Components is a great pattern that has proven to be very valuable for several React libraries. According to the official documentation of React -
A higher-order component (HOC) is an advanced technique in React for reusing component logic. HOCs are not part of the React API, per se. They are a pattern that emerges from React's compositional nature.
JavaScript is a well-suited language for functional programming as it can accept higher-order functions. A higher-order function is a function that can take another function as an argument and/or that returns a function as a result.
Higher-order functions allow us to abstract over actions, not just values. With HOCs we can wrap over our child component and either add business logic on top of it or extend the abilities of the child component itself.
What can I do with HOCs?
At a high-level HOC enables you to:
- Reuse code, reuse logic, and bootstrap abstraction
- Render Highjacking
- State abstraction and manipulation
- Props manipulation
Third-party React libraries, such as Redux or React Router, frequently use HOCs. I'm sure you've used some of them without even realising it.
In React, the main purpose of a higher-order component is to share common functionality between components without having to repeat code.
Types of HOCs
The two main ways of implementing HOCs in React are:
- Props Proxy (PP)
- Inheritance Inversion (II)
Both enable different ways of manipulating the WrappedComponent. Both are simply a function, that takes a Component as an argument and produces a new component containing the WrappedComponent.
Props Proxy
Props Proxy, as the name suggests, passes properties received from Higher-Order Component.
The crucial element here is that the HOC's render method returns a React Element of the WrappedComponent's type. The HOC receives what we pass through the props, hence the name props proxy. The HOC returns a React Element that describes what React should render in its reconciliation process.
You can also wrap the Wrapped Component with other JSX elements changing its UI according to your app needs.
Props Proxy HOCs are useful in the following situations:
- Manipulating props
- Accessing the instance via Refs
- Abstracting State
- Wrapping/Composing the WrappedComponent with other elements
Inheritance Inversion
This HOC can gain access to WrappedComponents instances. This provides us with access to the state, props, component lifecycle hooks, and the render method.
The returned HOC class (Enhancer) extends the WrappedComponent, as you can see. It's termed Inheritance Inversion because, instead of the WrappedComponent extending some Enhancer class, the Enhancer passively extends it. In this way, their relationship appears reversed.
Inversion Inheritance HOCs are useful for the following situations:
- Render Highjacking
- Manipulating state
Let's dive into some examples
To get a solid grip on the fundamentals we've learned, let's take an example of an application that has a single input that takes a name and changes the name.
Imagine we have a scenario where our business application requires lots of form validation and different use cases have different input validations, in such a case rather than duplication code and making multiple input forms with use case-based components, we can abstract it into a HOC which takes an input field or a little more of your child component and manipulates the states as well as the actions (validations, etc) and wraps your child component with the necessary business logic for each use case.
Consider the example below -
Here we have made Form
as the child component which is being wrapped around the withHandlers
HOC. It gives the child component its own freedom and doesn't overcomplicate the base component with overhead logic and justifies separation of concern.
The HOC is now in control to add/remove validations and any extra actions as deemed fit by the developer.
Conclusion
This was a relatively simple example to give you an idea of how the ideas work in practice. It takes some time to become accustomed to and comfortable with this type of abstraction, so don't lose the drive or focus with HOCs.
Also once you are comfortable and want more deep and complex explanations, I'd recommend checking out this detailed blog and exploring the concepts.
If I missed out on any point or you want to discuss something feel free to leave a comment down below, I'd hop in ASAP. 🌟
Lastly, Thank you for making it this far down into the article and showing your interest in React. You are amazing and keep making a positive difference every day. Peace out. ✌🏼
Top comments (0)