【问题标题】:Why is the syntax for higher order components in react often of the Higher Order Function form? Instead of extra arguments?为什么高阶组件的语法经常采用高阶函数形式?而不是额外的论点?
【发布时间】:2020-04-29 19:46:42
【问题描述】:

我想知道,为什么在反应中,我们经常看到表单的高阶组件:

MyComponent = withSomeHOC(params)(function MyActualCompoent(props) {
    return <div/>
})

实现可能如下所示:

function withSomeHOC(params, modifier) {
    function(WrappedComponent) {
        return function(props) {
            //do whatever to modify something based on params.
            const data = modifier(React.useContext(someCTX));
            return <>
                <div>{data}</div>
                <WrappedComponent {...props}/>
            </>;
        }
    }
}

而不是更合乎逻辑的方法(对我来说)只是将参数作为第二个(和第三个)参数添加到高阶组件本身:

MyComponent = withSomeHOC(function MyActualComponent(props) {
    return <div/>
}, params, modifier);


function(WrappedComponent, params, modifier) {
    return function(props) {
        //do whatever to modify something based on params.
        const data = modifier(React.useContext(someCTX));
        return <>
            <div>{data}</div>
            <WrappedComponent {...props}/>
        </>;
    }
}

为什么我们几乎看不到第二种方法,而几乎总是第一种?第二种的缺点是什么?一个优点是程序结构更简单,而不是深度嵌套的高阶组件和函数。

【问题讨论】:

    标签: reactjs higher-order-functions higher-order-components


    【解决方案1】:

    我推测这种情况如此普遍的一个原因是为了使构图更容易。如果您将多个 HoC 应用于单个组件,您最终可能会得到一些难以阅读的代码,如下所示:

    export default withLogging(withRouter(withStuff(Component, arg1a, arg2a), arg1b), arg1c);
    

    Recompose 或类似的库可以让您通过名为compose 的实用函数将其转换为更具可读性的内容。 compose 接受一系列函数并一次调用它们,将一个函数的输出作为输入传递给下一个函数。

    但为了使其工作,所有这些函数都必须是一元的(即,它们必须只接受一个参数)。因此,使用您所询问的模式的原因是它可以让您轻松制作一元函数,只需要将一个组件传递给它们。然后这些一元函数可以组合在一起。

    因此,如果 withLoggingwithRouterwithStuff 被重写以遵循您描述的模式,那么它们可以按如下方式使用:

    export default compose(
      withStuff(arg1a, arg2a),
      withRouter(arg1b),
      withLogging(arg1c),
    )(Component)
    

    【讨论】:

    • 因此,如果 recompose 已经有助于使代码在此处给出的示例中看起来更干净。实际使用多级“高阶函数”的原因是什么? - 我看不到这里的论点。 recompose 不能做你给出的例子吗?
    • Is recompose not able to do the example you have given? 为了使第二段代码能够工作,withStuffwithRouterwithLogging 必须全部编写为使用您想知道的模式。如果他们不使用该模式,那么第二段代码将不起作用。
    • 哦,您能否在您的帖子中明确说明/说明这一点。现在对我(可能是未来的读者)来说,您似乎建议“recompose 将在方案背后发挥魔力以在两种模式之间进行转换”。
    • 我已经重新安排并改写了我的答案。
    【解决方案2】:

    对于第一种形式,您可以配置该 HOC 工厂一次,然后在其他地方使用它。

    这实际上是一种装饰器模式。

    const preConfigDecorator = withSomeHOC(config)
    const DecoratedComp1 = preConfigDecorator(Comp1)
    const DecoratedComp2 = preConfigDecorator(Comp2)
    

    如果你的组件是基于类的,那么语法会更优雅:

    @withSomeHOC(config)
    class MyComp extends React.Component {
      …
    }
    

    【讨论】:

      【解决方案3】:

      我一直在阅读有关最近的 currying 和这个:

      MyComponent = withSomeHOC(params)(function MyActualCompoent(props) {
          return <div/>
      })
      

      在我看来是这样的:

      function(a)(a)
      

      从我阅读的内容来看,它是为了编写更简洁的代码。就像尼古拉斯说的。 不确定是否有任何性能优势。这是stackoverflow上的参考

      注意:我还是个学习者。

      【讨论】:

        猜你喜欢
        • 2020-03-18
        • 2020-06-15
        • 2019-09-25
        • 2021-03-13
        • 1970-01-01
        • 2019-12-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多