我正在学习React。在我看来,HOC喜欢React的官方docs中的以下示例:
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} />;
}
};
}
可以这样重写:
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 <component data={this.state.data} {...this.props} />;
}
}
然后像这样使用它:
<WithSubscription component={BlogPost} selectData={(DataSource) => DataSource.getComments()} />
他们都是HOC吗?什么时候比另一种更喜欢?
答案 0 :(得分:2)
他们所谓的“HOC”基本上是一个功能(只是常规功能,而不是特定于React),其行为类似于组件工厂。这意味着它输出包装的组件,这些组件是包装您选择的任何内部组件的结果 。您的选择是使用“WrappedComponent”参数指定的。 (注意他们所谓的“HOC”实际上如何返回一个类)。
所以我不知道为什么他们称之为“HOC”tbh。它只是一个吐出组件的功能。如果有人知道为什么我有兴趣听到原因。
本质上,他们的例子正在完成您正在做的事情,但它更灵活,因为WrappedComponent被作为参数使用。所以你可以指定你想要的任何东西。
另一方面,您的代码会将您的内部组件硬编码到其中。
要看到他们示例的强大功能,假设您有一个名为insideComp.js的文件,其中包含:
import withSubscription from './withSubscription';
class InsideComp extends React.Component{
// define it
}
export default withSubscription(InsideComp);
当你在另一个文件中使用insideComp时:
import myComp from './insideComp.js';
你实际上并没有导入insideComp,而是“withSubscription”已经吐出的包装版本。因为记住你的lastComp.js的最后一行是
export default withSubscription(InsideComp);
所以你的InsideComp在导出之前就被修改了
答案 1 :(得分:2)
起初我也在与HOC斗争。另一种看待这种情况的方法是使用组件包装来隔离一个组件的功能。
例如,我有多个HOC。我有很多只由props定义的组件,一旦创建它们就是不可变的。
然后我有一个Loader HOC组件,它处理所有的网络连接,然后只是将props传递给任何组件包装(这将是你传递给HOC的组件)。
加载器并不真正关心它正在呈现哪个组件,它只需要获取数据,并将其传递给包装组件。
在您的示例中,您实际上可以完成相同的操作,但是一旦您需要链接多个HOC,它将变得更加复杂。
例如,我有这个HOC链:
PermissionsHOC - &gt; LoaderHOC - &gt; BorderLayoutHOC - &gt;成分
第一个可以检查您的权限,第二个是加载数据,第三个是给出通用布局,第四个是实际组件。
如果您意识到某些组件可以从父级上的通用逻辑中受益,那么检测HOC会容易得多。您可以在示例中执行相同的操作,但是每次添加子组件时都需要修改HOC,以便为该组件添加逻辑。不是很有效。这样,您可以轻松添加新组件。我有一个基础组件,每个组件都扩展,但我用它来处理辅助功能,如分析,记录器,处理错误等。
答案 2 :(得分:0)
第二个不是HOC。
他们从higher order functions硬币HOC这个词。高阶函数的一个示例是将函数作为参数并返回另一个函数的函数。
类似地,HOC是一个将组件作为参数并返回另一个组件的函数。
这对我来说听起来很奇怪,因为更高阶的成分不是反应成分;这是一个功能。我猜他们称之为HOC的原因是:
react组件是一个类,它确实是JavaScript中的构造函数(除了功能组件只是函数)。 HOC实际上接受一个函数(一个构造函数)并返回另一个函数(另一个构造函数),所以如果你考虑它,它实际上是一个更高阶函数。可能是因为它处于反应环境中并且这是转换组件的模式,他们称之为HOC。
至于你提到的两种风格之间的区别:
第一个:您将使用第一个类来生成类似MyComponnet = withSubscription(AnotherComponent, ...)
的类,并且只要您在渲染调用中需要它,只需编写<MyComponent><MyComponent>
第二个:这不太常见。每次在渲染调用中需要它时,您都需要包含WithSubscription组件,如您在描述<WithSubscription component={BlogPost} selectData={(DataSource) => DataSource.getComments()} />