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中实现相同的目标?

首先,看起来有一个问题你必须修补。 这将在下一个单点版本中修复:只需将此方法添加到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 文档示例中一样)。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

最新更新