因此,在我的 React 应用程序中,我看到以下定义 HOC 的模式;
export function withMyApi() {
// Extra function wrapper to allow for clear place for configs. Plus, you can compose multiple HOCs if necessary
return function(WrappedComponent) {
class MyApiUrls extends React.Component {
constructor(props) {
super(props);
}
render() {
return <WrappedComponent api={this.api} {...this.props} />;
}
}
return MyApiUrls;
};
}
以上是如何工作的?HIC 是否在此处返回功能组件?上面的方式是故意用来组合的吗?
具体地说,一个 HOC 返回一个类组件或一个函数组件。但是,对于上述模式,尚不清楚 HOC 返回的是什么。
您问题中的函数是名称的 HOF(高阶函数),withMyApi
它返回一个匿名函数,该函数接受一个组件作为WrappedComponent
参数,该函数在调用时返回您传递的“组件”。
以下是使用此 HOF 的语法:
const MyComponent = withMyApi()(MyOriginalComponent)
是的,您可以说这withMyApi()(MyOriginalComponent)
是不必要的工作,它应该是withMyApi(MyOriginalComponent)
。
我同意。所以,这里是重构的 HOC:
选项 1,使用类组件作为包装器:
export function withMyApiClass(WrappedComponent) {
return class MyApiUrls extends React.Component {
constructor(props) {
super(props)
this.api = 'http://www.example.com'
}
render() {
return <WrappedComponent api={this.api} {...this.props} />
}
}
}
使用上述 HOC 的语法:const Comp1 = withMyApiClass(Comp)
.
选项 2,使用函数组件作为包装器:
export function withMyApiFunction(WrappedComponent) {
return function MyApiUrls(props) {
const api = useRef('http://www.example.com')
return <WrappedComponent api={api.current} {...props} />
}
}
使用上述 HOC 的语法:const Comp1 = withMyApiFunction(Comp)
.
那么,为什么我们需要withMyApi
HOF的第一种形式(有问题)?
您可能需要也可能不需要,这取决于您的要求。一个典型的用例是传递一些config
对象。一个例子:
export function withMyApi(config) {
const { secure } = config
return function (WrappedComponent) {
class MyApiUrls extends React.Component {
constructor(props) {
super(props)
this.api = `http${secure ? 's' : ''}://www.example.com`
}
render() {
return <WrappedComponent api={this.api} {...this.props} />
}
}
return MyApiUrls
}
}
使用上述 HOF 的语法:const Comp1 = withMyApi({ secure: false })(Comp)
.
PS:如果你曾经使用过 Redux,你一定见过connect HOF 它接受一些参数,类似于你的 HOF。
因此,编写 HOF 背后的基本思想是 -将配置参数与组件参数分开,以便人们compose
在有多个 HOC 使用时可以轻松使用功能。
您的问题:
有问题的 HOC 实际上是高阶函数:它返回一个函数,该函数在调用时返回一个组件。
不,它正在返回一个函数。但是当我们调用返回的函数时,它返回一个类组件。请参阅选项 2,它返回一个函数组件。
是的,当使用多个 HOC或HOF 时,您可以使用 compose 实用程序(来自任何库,如 - Ramdajs、Lodash或Redux)来创建新的“组合 HOC”。请参阅最大化可组合性。
是的,一个例子。假设我们在HOC下面写了:
export function withMyApi(WrappedComponent, config) {
const { secure } = config
return function MyApiUrls(props) {
const api = useRef(`http${secure ? 's' : ''}://www.example.com`)
return <WrappedComponent api={api.current} {...props} />
}
}
如何使用它?
const Comp1 = withMyApi(Comp, { secure: true })
/* OR, if you want to use more HOCs.
Nested (dirty? Maybe) */
const Comp1 = withRouter(withMyApi(Comp, { secure: true }))
-----------------------------------------------------------
// But you CAN NOT compose like this:
const composedHOC = compose(
withRouter, // a function : OK
withMyApi(Comp, { secure: false }) // NOT OK. Because is a React Component now.
)
/* It will give error when you will call composedHOC(...) because
in React, we don't call components using parenthesis i.e. () but
we invoke then using angle brackets i.e. < />. */
/* After compsing, you CAN NOT do the below otherwise you are going
to pass `Comp` 2 times to `withMyApi` : Bad/Confusing... :(
PLUS you will see errors due to calling a React Component using
parenthesis i.e. () as mentioned above. */
const Comp1 = composedHOC(Comp)
-----------------------------------------------------------
// But you can compose like the below:
const composedHOC = compose(
withRouter,
withMyApi
)
const Comp1 = composedHOC(Comp, { secure: false })
/* It will work because it will pass the TWO parameters - "Comp" &
"{ secure: false }" to LAST (withMyApi) HOC. And the result of that
will be passed to FIRST HOC (withRouter). */
-----------------------------------------------------------
// But, surprisingly, there will be error when you change the order:
const composedHOC = compose(
withMyApi, // FIRST
withRouter // LAST
)
const Comp1 = composedHOC(Comp, { secure: false })
/* Because it will pass the TWO parameters to LAST HOC (withRouter),
and result of that to FIRST HOC (withMyApi) and So, withMyApi will
receive ONLY enhanced "Comp" NOT the "{ secure: false }". This is why
using "compose" is buggy for HOCs that acpect config parameters. */
/* Just to remind, this is what a compose function does:
"Composes single-argument functions from right to left. The rightmost
function can take multiple arguments as it provides the signature for
the resulting composite function."
compose(f, g, h) is the same as (...args) => f(g(h(...args)))
Means, it pass args to h, and the result to g and then result to f. */
export function withMyApi(config) {
const { secure } = config
return function (WrappedComponent) {
return function MyApiUrls(props) {
const api = useRef(`http${secure ? 's' : ''}://www.example.com`)
return <WrappedComponent api={api.current} {...props} />
}
}
}
如何使用它?
const Comp1 = withMyApi({ secure: false })(Comp)
// OR, if you want to use more HOCs
const composedHOC = compose(
withRouter,
withMyApi({ secure: false })
)
const Comp1 = composedHOC(Comp) // Looks clean :)
compose
如果 HOC 接受“组件”和一个或多个“配置”对象,则不要与 HOC 一起使用。改用嵌套方法。compose
使用 HOF 和 HOC(只要 HOC 不接受配置对象)compose
您的 HOF。如果您想通过函数的附加参数来支持“配置”,那么 HOF 会更好/更干净。
这种 (HOF) 形式可能看起来令人困惑或不必要,但它有一个有用的特性。像 connect 函数返回的单参数 HOC 具有签名 Component => Component。输出类型与其输入类型相同的函数真的很容易组合在一起。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句