Higher Order Components (HOCs)
A higher-order component is a function that takes a component as parameter and returns a new component.
A Simple Higher Order Component
Example of a simple HOC.
import React from "react"
// Defining a HOC called 'withFavoriteNumber' and passing all components from 'App' component
export function withFavoriteNumber(component) {
    const Component = component
    return function(props){
        //  {...props} allows us to pass all props from 'App' component to our new Higher Order Component
        // 'favNum' is our new component's props 
        return <Component favNum="7" {...props} />
    }  
}import React from "react"
import {withFavoriteNumber} from "./withFavoriteNumber"
function App(props) {
    return (
        <div>
            {props.someProps} // output: Hi there!
            {props.favNum} // output: 7
        </div>
    )
}
// Passing App component within our HOC function
export default withFavoriteNumber(App)import React from "react"
import ReactDOM from "react-dom"
import App from "./App"
// 'someProps' is our App component's props
ReactDOM.render(<App someProps="Hi there!" />, document.getElementById("root"))
Sharing State with HOC
We can use HOC to achieve DRY principle & share logic between different components.
import React, {Component} from "react"
import {hocToggler} from "./HOCs/hocToggler"
function Favorite(props) {
    return (
        <div>
            <h3>Click heart to favorite</h3>
            <h1>
                <span 
                    onClick={props.toggle}
                >
                    {props.on ? "❤️" : "♡"}
                </span>
            </h1>
        </div>
    ) 
}
export default hocToggler(Favorite)import React, {Component} from "react"
class Toggler extends Component{
    state = {
        on: false
    }
    
    toggle = () => {
        this.setState(prevState => {
            return {
                on: !prevState.on
            }
        })
    }
    
    render() {
        const {component: C, ...props} = this.props
        return (
            <C on={this.state.on} toggle={this.toggle} {...props} />
        )
    }
}
export function hocToggler(component){
    return function(props){
        return(
            <Toggler component={component} {...props} />
        )
    }
}HOC can even take default props.
import React from "react"
import {hocToggler} from "./hocToggler"
// Functional component
function Favorite(props){
    return(
        <div>
            <h3>Click heart to favorite</h3>
            <h1>
                // Deriving method from HOC
                <span 
                    onClick={props.toggle} 
                >
                // Deriving state from HOC
                    {props.on ? "❤️" : "♡"}
                </span>
            </h1>
        </div>
    ) 
}
// Passing components & optionObjects to HOC
export default hocToggler(Favorite, {defaultOnValue:false})import React, {Component} from "react"
class Toggler extends Component{
    // Shared state for both 'Favorite' & 'Menu' components
    state = {
        on: this.props.defaultOnValue
    }
    
    // Shared method for both 'Favorite' & 'Menu' components
    toggle = () => {
        this.setState((prevState)=>{
            return {
                on: !prevState.on
            }
        })
    }
    
    render(){
        // Functional component's properties are passed down here
        const Component = this.props.component
        
        return(
            // Creating a new supercharged component with Functional component's properties with HOC's own state & method
            <Component on={this.state.on} toggle={this.toggle} {...this.props} />
        )
        
    }
}
// HOC functions
export function hocToggler(component, optionsObj){ // `component` parameter refers to `favorite` & `menu` components
    return function(props){
        // Receiving Functional component's properties
        return(
            <Toggler component={component} defaultOnValue={optionsObj.defaultOnValue} {...props} />
        )
    }
}import React from "react"
import Menu from "./Menu"
import Favorite from "./Favorite"
function App() {
    return (
        <div>
            <Menu />
            <hr />
            <Favorite />
        </div>
    )
}
export default Appimport React from "react"
import ReactDOM from "react-dom"
import App from "./App"
ReactDOM.render(<App />, document.getElementById("root"))Last updated
Was this helpful?