代码之家  ›  专栏  ›  技术社区  ›  Derek 朕會功夫

链或组合多个“补丁”的好方法?

  •  1
  • Derek 朕會功夫  · 技术社区  · 7 年前

    在React中,这是一种非常常见的模式,我们“修补”一个组件,它将接收自定义属性:

    export default gimmeMahProps(someRandomSettings)(MyComponent);
    

    示例:

    // Redux
    connect(stateMapper, dispatchMapper)(MyComponent);
    
    // Material UI
    withStyles(myStyles)(MyComponent);
    

    当我们拥有越来越多的这些功能时,这可能会变得相当混乱:

    // messy nested function calls with only two of those patchers
    export default connect(stateMapper, dispatchMapper)(withStyles(myStyles)(MyComponent));
    

    这就是我现在要做的,以避免嵌套函数调用的金字塔:

    export default [
        connect(stateMapper, dispatchMapper),
        withStyles(myStyles)
    ].reduce((comp, patcher) => patcher(comp), MyComponent);  // kind of a hack
    

    更具可读性,但我所寻找的是一种更简单的方式,链或结合在一起也许我遗漏了一些东西,但是React是否提供了实现这一点的API?

    2 回复  |  直到 7 年前
        1
  •  2
  •   amankkg    7 年前

    是的,它的名字是 功能构成 ,函数编程中的基本“模式”之一(或者在任何语言中,函数都是一流的公民,JavaScript也是如此)。

    你可以看看 compose from redux

    或者,我还是选拉姆达的好 compose (从右向左应用)或 pipe (从左到右应用程序)简而言之:

    compose(fn1, fn2)(x) === fn1(fn2(x))
    pipe(fn1, fn2) === fn2(fn1(x))
    

    你的丑陋代码的例子可以这样写

    const enhance = pipe(
      withStyles(myStyles),
      connect(stateMapper, dispatchMapper),
    )
    
    export default enhance(MyComponent)
    

    另外,请注意,有一个即将推出的语言特性称为 pipeline operator .

        2
  •  1
  •   Jee Mok ecanf    7 年前

    使用JavaScript装饰器怎么样?

    @connect(stateMapper, dispatchMapper)
    @withStyles(myStyles)
    export default class App extends Component {
        ...
    

    有一个很棒的图书馆叫 Core Decorators 它提供了一些非常有用的通用装饰器,现在可以使用了这些通常允许非常有用的通用功能(例如方法调用的计时、弃用警告、确保值是只读的),但使用更干净的decorator语法。