React: Pattern: Reusable Component: Higher-Order Components

20th August 2020 at 2:19pm
React: Pattern: Reusable Component

高阶组件(HOC, Higher-Order Components),本质上是利用了 JavaScript 中,函数及 class 作为一等公民的能力来实现的一种 pattern。

React 文档 给了一个好的例子:

// This function takes a component...
function withSubscription(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(DataSource, props)
      };
    }

    componentDidMount() {
      // ... that takes care of the subscription...
      DataSource.addChangeListener(this.handleChange);
    }

    componentWillUnmount() {
      DataSource.removeChangeListener(this.handleChange);
    }

    handleChange() {
      this.setState({
        data: selectData(DataSource, this.props)
      });
    }

    render() {
      // ... and renders the wrapped component with the fresh data!
      // Notice that we pass through any additional props
      return <WrappedComponent data={this.state.data} {...this.props} />;
    }
  };
}

用法:

const CommentListWithSubscription = withSubscription(
  CommentList,
  (DataSource) => DataSource.getComments()
);

const BlogPostWithSubscription = withSubscription(
  BlogPost,
  (DataSource, props) => DataSource.getBlogPost(props.id)
);

上面例子中,CommentListBlogPost 组件,只需要实现自己的 render() 函数,即可通过相应的 WithSubscription 组件获得自动监听信息源的能力。这种添加和移除监听事件的能力,就在两个组件间复用。关键的技术点是:

  • withSubscription() 返回一个 class
  • DataSource 中获取数据的过程,通过 selectData 来传递