React - 高阶组件应该写成一个函数吗?
React - should Higher Order Component be written as a function?
我正在学习 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 吗?什么时候一种风格比另一种更受欢迎?
他们所说的 "HOC" 基本上是一个行为类似于组件工厂的函数(只是一个常规函数,不是特定于 React 的)。这意味着它输出的包装组件是包装任何您选择的内部组件的结果。您的选择是用 "WrappedComponent" 参数指定的。 (注意他们所谓的"HOC"实际上是returns一个class)。
所以我不知道他们为什么称它为 "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" 已经吐出的包装版本。因为记住你的最后一行 insideComp.js 是
export default withSubscription(InsideComp);
所以你的 InsideComp 在导出之前被修改了
一开始我也在为 HOC 苦苦挣扎。另一种看待这个问题的方法是查看组件的包装器,您可以使用它来将功能与一个组件隔离开来。
比如我有多个HOC。我有许多仅由 props 定义的组件,它们一旦创建就不可更改。
然后我有一个 Loader HOC 组件,它处理所有网络连接,然后将 props 传递给任何正在包装的组件(这将是您传递给 HOC 的组件)。
加载器并不真正关心它正在渲染哪个组件,它只需要获取数据,并将其传递给包装的组件。
在您的示例中,您实际上可以完成相同的操作,但是一旦您需要链接多个 HOC,它就会变得更加复杂。
例如我有这个 HOC 链:
PermissionsHOC -> LoaderHOC -> BorderLayoutHOC -> 组件
第一个可以检查您的权限,第二个可以加载数据,第三个可以提供通用布局,第四个是实际组件。
如果您意识到某些组件会受益于在父级上具有通用逻辑,那么检测 HOC 会容易得多。您可以在示例中执行相同的操作,但是每次添加子组件时都需要修改 HOC,以添加该子组件的逻辑。不是很有效。这样,您可以轻松添加新组件。我确实有一个 Base 组件,每个组件都扩展了它,但我用它来处理辅助功能,如分析、记录器、处理错误等。
第二个不是 HOC。
他们从 higher order functions 中创造了 HOC 这个词。高阶函数的一个示例是将函数作为参数和 returns 另一个函数的函数。
类似地,HOC 是一个函数,它将一个组件作为参数,returns 另一个组件。
这对我来说听起来很奇怪,因为高阶组件不是 React 组件;它是一个函数。我猜他们称它为 HOC 的原因是:
一个react组件就是一个class,在JavaScript中确实是一个构造函数(除了函数式组件就是简单的函数)。 HOC 实际上接受一个函数(一个构造函数)和 returns 另一个函数(另一个构造函数),所以如果你考虑一下它实际上是一个高阶函数。可能是因为它在反应上下文中,这是一种转换组件的模式,他们称之为 HOC。
关于你说的两种风格的区别:
第一个:您将使用第一个来生成 class,例如 MyComponnet = withSubscription(AnotherComponent, ...)
,只要您在渲染调用中需要它,只需编写 <MyComponent><MyComponent>
第二个:这种不太常见。每次在渲染调用中需要它时,都需要包含描述中提到的 WithSubscription 组件 <WithSubscription component={BlogPost} selectData={(DataSource) => DataSource.getComments()} />
我正在学习 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 吗?什么时候一种风格比另一种更受欢迎?
他们所说的 "HOC" 基本上是一个行为类似于组件工厂的函数(只是一个常规函数,不是特定于 React 的)。这意味着它输出的包装组件是包装任何您选择的内部组件的结果。您的选择是用 "WrappedComponent" 参数指定的。 (注意他们所谓的"HOC"实际上是returns一个class)。
所以我不知道他们为什么称它为 "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" 已经吐出的包装版本。因为记住你的最后一行 insideComp.js 是
export default withSubscription(InsideComp);
所以你的 InsideComp 在导出之前被修改了
一开始我也在为 HOC 苦苦挣扎。另一种看待这个问题的方法是查看组件的包装器,您可以使用它来将功能与一个组件隔离开来。
比如我有多个HOC。我有许多仅由 props 定义的组件,它们一旦创建就不可更改。
然后我有一个 Loader HOC 组件,它处理所有网络连接,然后将 props 传递给任何正在包装的组件(这将是您传递给 HOC 的组件)。
加载器并不真正关心它正在渲染哪个组件,它只需要获取数据,并将其传递给包装的组件。
在您的示例中,您实际上可以完成相同的操作,但是一旦您需要链接多个 HOC,它就会变得更加复杂。
例如我有这个 HOC 链:
PermissionsHOC -> LoaderHOC -> BorderLayoutHOC -> 组件
第一个可以检查您的权限,第二个可以加载数据,第三个可以提供通用布局,第四个是实际组件。
如果您意识到某些组件会受益于在父级上具有通用逻辑,那么检测 HOC 会容易得多。您可以在示例中执行相同的操作,但是每次添加子组件时都需要修改 HOC,以添加该子组件的逻辑。不是很有效。这样,您可以轻松添加新组件。我确实有一个 Base 组件,每个组件都扩展了它,但我用它来处理辅助功能,如分析、记录器、处理错误等。
第二个不是 HOC。
他们从 higher order functions 中创造了 HOC 这个词。高阶函数的一个示例是将函数作为参数和 returns 另一个函数的函数。
类似地,HOC 是一个函数,它将一个组件作为参数,returns 另一个组件。
这对我来说听起来很奇怪,因为高阶组件不是 React 组件;它是一个函数。我猜他们称它为 HOC 的原因是:
一个react组件就是一个class,在JavaScript中确实是一个构造函数(除了函数式组件就是简单的函数)。 HOC 实际上接受一个函数(一个构造函数)和 returns 另一个函数(另一个构造函数),所以如果你考虑一下它实际上是一个高阶函数。可能是因为它在反应上下文中,这是一种转换组件的模式,他们称之为 HOC。
关于你说的两种风格的区别:
第一个:您将使用第一个来生成 class,例如 MyComponnet = withSubscription(AnotherComponent, ...)
,只要您在渲染调用中需要它,只需编写 <MyComponent><MyComponent>
第二个:这种不太常见。每次在渲染调用中需要它时,都需要包含描述中提到的 WithSubscription 组件 <WithSubscription component={BlogPost} selectData={(DataSource) => DataSource.getComments()} />