Skip to content

Latest commit

 

History

History
102 lines (86 loc) · 2.88 KB

15.higher-order-component.md

File metadata and controls

102 lines (86 loc) · 2.88 KB

Higher Order Component

A higher-order function is a function that takes and/or returns a function. It’s not more complicated than that. So, what’s a higher-order component? If you’re already using container components, these are just generic containers, wrapped up in a function.

Higher-order components look really similar to the decorator design pattern. It is wrapping a component and attaching some new functionalities or props to it.

/**
 * SIMPLE EXAMPLE
 */
// HOC
import { Component } from "React";
export var Enhance = ComposedComponent => class extends Component {
  constructor() {
    this.state = { data: null };
  }
  componentDidMount() {
    this.setState({ data: 'Hello' });
  }
  render() {
    return <ComposedComponent {...this.props} data={this.state.data} />;
  }
};

// HOC Usage
import { Enhance } from "./Enhance";
class MyComponent {
  render() {
    if (!this.data) return <div>Waiting...</div>;
    return <div>{this.data}</div>;
  }
}
export default Enhance(MyComponent); // Enhanced component

/**
 * MORE DETAILED
 */

// Let’s start with our stateless Greeting component.
const Greeting = ({ name }) => {
  if (!name) { return <div>Connecting...</div> }

  return <div>Hi {name}!</div>
};

// If it gets props.name, it’s gonna render that data. Otherwise it’ll say that it’s “Connecting…”.
// Now for the higher-order bit.

const Connect = ComposedComponent =>
  class extends React.Component {
    constructor() {
      super();
      this.state = { name: "" }
    }

    componentDidMount() {
      // this would fetch or connect to a store
      this.setState({ name: "Michael" })
    }

    render() {
      return (
        <ComposedComponent
          {...this.props}
          name={this.state.name}
        />
      )
    }
  };

// This is just a function that returns component that renders the component
// we passed as an argument.
// Last step, we need to wrap our our Greeting component in Connect.

const ConnectedMyComponent = Connect(Greeting);
// This is a powerful pattern for providing fetching and providing data to any
// number of stateless function components.


// Advantage of using HOC:
// HOCs give us control on the input data that we want to send as props.
// Let's say that we have a configuration setting that OriginalComponent needs:

var config = require('path/to/configuration');

var enhanceComponent = (Component) =>
  class Enhance extends React.Component {
    render() {
      return (
        <Component
          {...this.state}
          {...this.props}
          title={ config.appTitle }
        />
      )
    }
  };

The knowledge for the configuration is hidden into the higher-order component. OriginalComponent knows only that it receives a prop called title. Where it comes from it is not important. That's a huge advantage because it helps us testing the component in an isolation and provides nice mechanism for mocking.