react js component

What is Higher order component?

Higher-order components (HOCs) in React concept originally came from the JavaScript’s higher-order components. A HOC is a method for reusing similar code in React components. It is a design derived from the compositional nature of React. It has been among the new features of React v18 that enables to learn higher order functions just as in JavaScript

HOCs essentially include the programming idea of don’t-repeat-yourself (DRY), which you’ve most likely encountered at some point in your career as a software developer. It is one of the most well-known software development principles, and the implementation of HOCs is quite critical while developing an application or writing code in general.

Higher-order functions in JavaScript

Before getting into HOCs in React, let’s take a quick look at higher-order functions in JavaScript. Understanding them is essential for understanding how HOCs work in to react.

Higher-order JavaScript functions accept certain functions as arguments and return another function. They allow us to abstract from actions rather than just values. They come in a variety of formats, and they allow us to write fewer lines of code when working with functions and even arrays.

Composition is the most interesting feature of using higher-order functions. Small functions that handle a single piece of logic can be written. Then, utilizing the various tiny functions we’ve written, we may assemble complex functions. This minimizes the number of defects in our code base and makes it much easier to read and understand.

Higher-order components in Reactjs

A higher-order component (HOC) is a more advanced React approach for reusing component logic. HOCs are not a component of the React API in and of themselves. They are a pattern that comes from the compositional structure of React.

A higher-order component wraps one component and returns a new component with the required functionality.

Third-party React libraries, such as Redux’s connect and Relay’s createFragmentContainer uses HOCs a lot.

Example

Assume you have a CommentList component that subscribes to an external data source in order to display a list of comments.

class CommentList extends React.Component {

    constructor(props) {

        super(props);

        this.handleChange = this.handleChange.bind(this);

        this.state = {

            // “Data” is some global data source

            comments: Data.cmts(),

        };

    }

    componentDidMount() {

        // Subscribe to changes

        DataSource.addChangeListener(this.handleChange);

    }

    handleChange() {

        // Update the state of component whenever the data source changes

        this.setState({

            cmts: Data.cmts(),

        });

    }

    render() {

        return (

            <div>

                {this.state.comments.map((cmt) => (

                    <Comment comment={cmt} key={cmt.id} />

                ))}

            </div>

        );

    }

}

Now, there is another component that follows a similar structure to subscribing to a single blog post.

class BlogPost extends React.Component {

    constructor(props) {

        super(props);

        this.handleChange = this.handleChange.bind(this);

        this.state = {

            blogPost: Data.getBlogPost(props.id),

        };

    }

    componentDidMount() {

        Data.addChangeListener(this.handleChange);

    }

    componentWillUnmount() {

        Data.removeChangeListener(this.handleChange);

    }

    handleChange() {

        this.setState({

            blogPost: Data.getBlogPost(this.props.id),

        });

    }

    render() {

        return <Block text={this.state.blogPost} />;

    }

}

Now, in the examples, BlogPost and CommentList are not identical. Methods performed on data are different in both the components, and the output is also different from both the components, but the implementation of both the components is very similar to each other.

  • On componentdidMount, both the components add a listener to data.
  • In the components the states are being set by the setState() method available in react.
  • In a complex project this setState() method gets called or invoked so many times. it affects the performance of the application that is the reason we require HOCs that allow us to write logic only one time and we can share that logic among the different components.

To reuse the logic we can create a method that generates components that subscribe to data, such as CommentList and BlogPost. A child component that receives the subscription data as a prop will be wrapped as one of the function’s parameters. Let us refer to this function as “subscribe.”

const CommentListSubscription = subscribe(CommentList, (Data) =>

    Data.getComments()

);

const BlogPostSubscription = subscribe(BlogPost, (Data, props) =>

    Data.getBlogPost(props.id)

);

How to create Higher-order component

The wrapped component is the first parameter. and the second parameter in HOCs components is data or the props that are required for implementation.

When CommentListWithSubscription and BlogPostWithSubscription are rendered, they will be handed a data prop with the most recent data from Data.

// This function takes a component…

function subscribe(WrappedComponent, selectData) {

    // …and returns another component…

    return class extends React.Component {

        constructor(props) {

            super(props);

            this.handleChange = this.handleChange.bind(this);

            this.state = {

                data: selectData(Data, props),

            };

        }

        componentDidMount() {

                       Data.addChangeListener(this.handleChange);

        }

        componentWillUnmount() {

            Data.removeChangeListener(this.handleChange);

        }

        handleChange() {

            this.setState({

                data: selectData(Data, this.props),

            });

        }

        render() {

            return <WrappedComponent data={this.state.data} {…this.props} />;

        }

    };

}

The input components that get wrapped into HOCs do not inherit single behavior. Rather, a HOC wraps the original component in a container component to compose it. You can not make any side effects in HOC functions.

So there you have it! The wrapped component receives all of the container’s props, as well as a new prop, data, which it uses to create its result. The wrapped component has nothing to do with how or why the data is utilized, and the HOC isn’t concerned with where the data comes from.

The subscribe function is normal to react function, so you can pass as many parameters as you wish. For example, to further isolate the HOC from the wrapped component, you can name props according to their use case so the code becomes more understandable. You might also take an argument that configures shouldComponentUpdate or the data. All these functionalities are available and can be used because the HOCs have complete control over how the functions operate.

When we talk about the HOCs,

We do not alter or mutate components. We make new ones.

A HOC is used to wrap the functionality of one component and reuse it in the other component.

A HOC is a function. so we can not create any side effects and it only returns a new component.

Use Cases of Higher-Order Components

  • To display a loader while a component awaits data
  • To conditionally render components in react the way
  • To give specific styles for the components
  • To provide any props you want for the components,

 Limitations of Higher-Order Components

  • We can not create HOCs inside the render method.
  • Static methods should be copied over.
  • We can not pass refs in HOCs.

Conclusion

Higher-order components are mostly used to improve the reusability of specific components in numerous modules or components. We can also combine different components to create better components. The majority of third-party libraries use this functionality to create another great library.

By Anurag Rathod

Anurag Rathod is an Editor of Appclonescript.com, who is passionate for app-based startup solutions and on-demand business ideas. He believes in spreading tech trends. He is an avid reader and loves thinking out of the box to promote new technologies.