Using Higher Order Components in a React Application

If you have started using ReactJS recently often you might have felt that you are performing repeated logic in many components. For example consider an app having:

Infinite scroll in three different views with all - having different data. You want to fetch new set of data when you scroll to the current limit.

If you ever thought “Is there a way by which I can simplify this such that I don’t need to rewrite the fetching logic again and again in all three views?”. Well Higher Order Component (HOC) provides solution to such a kind of problems.

HOC is a powerful tool based on which many libraries are getting developed. The objective of this article is to explain about how HOCs can help in simplifying and abstracting repeated logic in a React Applications.

Javascript in general can be treated as functional programming or object orient programming. HOCs are functional implementation of javascript. It has its similarities with the concept of Higher Order functions.

Functions that operate on other functions, either by taking them as arguments or by returning them, are called higher-order functions.

For example

function greaterThan ( a ) { return function ( b ) { return b > a ; } }

greaterThan(10)(11) will be true.

Also we can do

var greaterThan10 = greaterThan ( 10 ) ;

And anywhere we can use greaterThan10(11) [ Which will be true ] . This helps in abstraction the inner details thereby giving us ability to think about higher level.

Higher Order components are based on this. Given a function (Functional component) which takes a component and gives back another component.

Function(component) => (component)

1. How it benefits in abstracting repeated logic?

A function (Functional component in React) which takes a component and gives back another component. We do this because we can do something inside the function which can add more power to the resulting component.

We can treat this as inheritance in React. How? We can treat the input functional component as a Parent and the resultant as the inherited components. So the exact benefits are:

Add / Update New props. Filter out props. Reuse Logic by maintaining an internal State. Change the Rendering of component based on any logic.

2. How To write a Higher order component.

Functional components started from React V15. It can be created like

import React from 'react' ; export const WrapperComponent ( WrappedComponent ) => { return class HigherOrderComponent extends React . Component { render ( ) { return ( < WrappedComponent { ... props } / > ) ; } } } const FirstHOC = WrapperComponent ( FirstComponent ) ; const SecondHOC = WrappedComponent ( SecondComponent ) ;

3. Usage

Lets try to create a Higher order component for a particular use case. Lets consider we have an app which has many tables. Each table can have any number of these three functionality ( can have multiple)

Pagination – On clicking each page number, fetches new data correspondingly. Sorting based on each column title in ascending or descending order. Changing Number of rows per page (Limit). The view would look something similar to this

The best way to structure is to have three separate logic for pagination, sorting and changing numbers per page. And whenever the parent component needs to conditionally render any of these then it can be done based on props.

import React from 'react' ; export const TableWrapper ( WrappedComponent ) => { return class TableComponent extends React . Component { constructor ( props ) { super ( props ) ; this . state = { tableData : null ; } ; } fetchMoreData ( limit , offset , sortBasedOn ) { const tableData = fetch ( endpoint , params ) this . setState ( { tableData , } ) } onChangeLimit ( changedLimit ) { fetchMoreData ( changedLimit , offset , sortBasedOn ) } onChangeOffset ( changedOffset ) { fetchMoreData ( limit , changedOffset , sortBasedOn ) ; } onChangeSortPriority ( currentSortBasedOn ) { fetchMoreData ( limit , changedOffset , currentSortBasedOn ) } render ( ) { return ( ( props . sortingRequired ? < Sorting { ... sortingRelatedProps } onChangeSortPriority = { this . onChangeSortPriority } / > : null ) ( < WrappedComponent { ... props } { ... this . state . tableData } / > ) ( props . changeNumberOfRowsRequired ? < ChangeNumberOfRowsPerPage { ... numberOfRowsPerPageRelatedProps } onChangeLimit = { this . onChangeLimit } / > : null ) ( props . paginationRequired ? < Pagination { ... paginationRelatedProps } onChangeOffset = { this . onChangeOffset } / > : null ) ) ; } } }

For this to make work all you need is a presentational component which renders Table cells based on some data. Lets say < Table /> is such a component then,

const WrappedTable = TableWrapper ( < Table / > ) ; const WrappedTable = TableWrapper ( < Table paginationRequired = { true } / > ) ; const WrappedTable = TableWrapper ( < Table paginationRequired = { true } changeNumberOfRowsRequired = { true } sortingRequired = { true } / > ) ;

Also we can see data fetching and this.state.tableData is completely abstracted inside of the HOC.

This structure can help us to write HigherOrder component at multiple level one over the other. For example the same can be achieved by writing three higher order components if we carefully interlink the abstraction. If we do that then we can have something like

const WrappedTable = PaginationWrapper ( SortingWrapper ( ChangeLimitWrapper ( < Table / > ) ) ) ;

But there are certain disadvantages in this method. This will create three React classes as supposed to one in the previous method. Also HOCs in common might have performance issues if there are too many props linking each functionality. One must use ShouldComponentUpdate lifecycle in order to avoid that.

But apart from that if we are careful enough we can have an architecture which can abstract logic that can be shared across other presentational components using HOC has great benefits.

Proceed to next part of this blog for a more functional approach to Higher Order Components