定义 React HOC 组件的风格

测试频道

因此,在我的 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).


那么,为什么我们需要withMyApiHOF的第一种形式(有问题)

您可能需要也可能不需要,这取决于您的要求。一个典型的用例是传递一些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 实际上是高阶函数:它返回一个函数,该函数在调用时返回一个组件。

HOF 是否在这里返回一个函数组件?

不,它正在返回一个函数。但是当我们调用返回的函数时,它返回一个类组件请参阅选项 2,它返回一个函数组件。

上面的方式是不是故意用的可以作曲?

是的,当使用多个 HOCHOF 时,您可以使用 compose 实用程序(来自任何库,如 - RamdajsLodashRedux)来创建新的“组合 HOC”。请参阅最大化可组合性


编辑:

我不喜欢 HOF。我还能实现组合和配置吗?

是的,一个例子。假设我们在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. */

好吧,我可能喜欢 HOF。如何使用 HOF 做同样的事情?

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 :)

结论:

  1. compose如果 HOC 接受“组件”和一个或多个“配置”对象,则不要与 HOC 一起使用改用嵌套方法。
  2. 使用嵌套或更好 -compose使用 HOF 和 HOC(只要 HOC 不接受配置对象)
  3. 这是最好的时候要接受一个/越写HOFs配置对象。这样,人们就可以使用compose您的 HOF。

如果您想通过函数的附加参数来支持“配置”,那么 HOF 会更好/更干净。

这种 (HOF) 形式可能看起来令人困惑或不必要,但它有一个有用的特性。像 connect 函数返回的单参数 HOC 具有签名 Component => Component。输出类型与其输入类型相同的函数真的很容易组合在一起。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章