Hyperstack中的高阶组件

时间:2019-04-05 16:38:05

标签: javascript ruby reactjs hyperstack

在javascript库中经常有一个用例,您想在其中用高阶组件装饰组件。

例如,material-ui库包含样式较高的组件withStyles

在javascript中,您会这样做

import { withStyles } from '@material-ui/core';

const styles = {
  example: {
    padding: 8
  }
}
const SomeComponent = ({classes}) => <div className={classes.example}>I'm a component</div>;

export default withStyles(SomeComponent);

如何在Hyperstack中实现相同的目标?

1 个答案:

答案 0 :(得分:2)

首先,您似乎需要修补issue。下一版本将解决此问题:只需将此方法添加到Hypercomponent基类(app/hyperstack/components/hypercomponent.rb

def self.to_n
  Hyperstack::Internal::Component::ReactWrapper.create_native_react_class(self)
end

现在,如果您具有以下样式:

MY_STYLES = {root: {backgroundColor: 'red'}}

以及要设置样式的组件:

class StyleTest < HyperComponent
  param :some_param
  param :classes
  render do
    DIV(class: classes[:root]) { some_param }
  end
end

您可以这样做:

class StyledTest1 < HyperComponent
  imports `Mui.withStyles(#{MY_STYLES.to_n})(#{StyleTest.to_n})`
end

发生的事情是,我们使用反引号退出了JS,直接调用Mui.with_styles并将其传递给MY_STYLES(就像在MUI doc示例中一样)。 to_n从Ruby Hash转换为JS对象。 (将参数传递给组件时,这是自动的,但对于简单的函数调用则不是这样。)

然后,我们用StyleTest类调用生成的HOC(也调用to_n从Ruby类转换为简单的JS类。)

最后,我们将其重新导入到Hyperstack组件类中。

比我喜欢的工作还多,所以我们可以在HyperComponent类中添加一个方便的帮助器方法:

class HyperComponent
  include Hyperstack::Component
  include Hyperstack::State::Observable
  param_accessor_style :accessors  # this is now the prefered param style

  # patch for issue: https://github.com/hyperstack-org/hyperstack/issues/153
  def self.to_n
    Hyperstack::Internal::Component::ReactWrapper.create_native_react_class(self)
  end

  # our helper macro:
  def self.add_styles(style, opts = {})
    imports `Mui.withStyles(#{style.to_n}, #{opts.to_n})(#{superclass.to_n})`
  end
end

现在我们可以添加如下样式:

class StyledTest2 < StyleTest
  add_styles MY_STYLE
end

现在我们有了一个带有样式的新组件类。

例如:

class App < HyperComponent

  render do
    DIV do
      StyledTest1(some_param: 'test 1')
      StyledTest2(some_param: 'test 2')
    end
  end
end