You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React高阶组件:函数式与类式写法辨析及适用场景

Are Both Approaches Higher-Order Components?

First, the short answer: No, only the first one is a true HOC. Here's why:

  • The first approach (withSubscription) is a function that accepts a WrappedComponent and selectData parameter, then returns a new enhanced component. This fits the exact HOC definition from React's official docs.
  • The second approach (WithSubscription) is a regular class component that accepts a component prop (and selectData) to render. This is actually a variant of the Component-as-Prop pattern (a cousin of Render Props), not an HOC. HOCs are always functions, not components themselves.
Breakdown of Each Approach

1. The HOC Function (withSubscription)

This is the classic HOC implementation:

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} />; 
    } 
  }; 
}

Usage:

// Pre-create the enhanced component once
const BlogPostWithSubscription = withSubscription(
  BlogPost, 
  (DataSource) => DataSource.getComments()
);

// Use it like any other component
<BlogPostWithSubscription />

2. The Component-as-Prop Class (WithSubscription)

This is a flexible component that takes another component as a prop to render. I fixed a small bug in your original code (referencing this.props.component instead of <component /> to avoid rendering an invalid HTML tag):

class WithSubscription extends React.Component { 
  constructor({ component, selectData, ...props }) { 
    super(props); 
    this.handleChange = this.handleChange.bind(this); 
    this.state = { data: selectData(DataSource, props) }; 
  } 
  componentDidMount() { 
    DataSource.addChangeListener(this.handleChange); 
  } 
  componentWillUnmount() { 
    DataSource.removeChangeListener(this.handleChange); 
  } 
  handleChange() { 
    this.setState({ data: selectData(DataSource, this.props) }); 
  } 
  render() { 
    return <this.props.component data={this.state.data} {...this.props} />; 
  } 
}

Usage:

// Dynamically pass the component and select logic each time you use it
<WithSubscription 
  component={BlogPost} 
  selectData={(DataSource) => DataSource.getComments()} 
/>
When to Use Each Approach

Use the HOC Function If:

  • You want to pre-configure an enhanced component for repeated use. For example, if you need the subscription logic attached to BlogPost in multiple places, creating BlogPostWithSubscription once keeps your code DRY.
  • You're building reusable utilities or library code. HOCs like Redux's connect or React Router's withRouter follow this pattern because they let users wrap their components with fixed logic.
  • You prefer a more "static" enhancement—once the HOC is applied, the wrapped component and logic are tied together unless you create a new enhanced component.

Use the Component-as-Prop Class If:

  • You need dynamic flexibility—for example, using the same subscription logic with different components (e.g., sometimes BlogPost, sometimes CommentList) without pre-creating multiple enhanced components.
  • You want to configure the logic at render time instead of upfront. This is great for one-off uses or cases where the select logic or target component might change based on props.
  • You prefer a more explicit, declarative approach where the relationship between the enhancer and component is visible directly in the JSX.

内容的提问来源于stack exchange,提问作者Shawn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:48:41