gle*_*nsl 4 interop reason higher-order-components bucklescript reason-react
假设我有一个高阶组件,类似于下面的琐碎定义,是从JavaScript模块导出的./hoc.js
:
export const withStrong =
Component => props =>
<strong> <Component ...props/> </strong>
Run Code Online (Sandbox Code Playgroud)
假设我有一个名为的组件HelloMessage
,那么这段JavaScript是等效的:
import { withStrong } from './hoc.js';
const HelloMessage = ...
const StrongMessage = withStrong(HelloMessage);
ReactDOM.render(
<StrongMessage name="Joe" />,
document.getElementById('react-app')
);
Run Code Online (Sandbox Code Playgroud)
TL; DR:
这应该与所请求的JavaScript代码段完全相同:
[@bs.module ./hoc.js]
external withStrong
: React.component('props) => React.component('props)
= "withStrong";
module HelloMessage = ...
module StrongMessage = {
include HelloMessage;
let make = withStrong(make);
};
ReactDOMRe.renderToElementWithId(
<StrongMessage name="Joe" />,
"react-app"
);
Run Code Online (Sandbox Code Playgroud)
在Reason操场上还有一个可运行的示例,其中进行了一些修改,以解决没有单独的JavaScript文件的问题。
解释如下:
withStrong
只是一个功能。它恰好是一个接受并返回一个react组件的函数,这有点神秘,但实际上它们只是其他值。我们可以像普通函数一样绑定它。
甚至像这样简单的事情都会起作用
[@bs.module ./hoc.js]
external withStrong : 'a => 'a = "withStrong";
Run Code Online (Sandbox Code Playgroud)
假设您始终确保传递组件。但这并不是特别安全,因为您还可以通过其他任何方式来传递它,因此让我们尝试使用应使用的类型系统,将其限制为仅接受反应组分。
该ReasonReact源代码表示的组件有型component('props)
,所以这就是我们将使用。
[@bs.module ./hoc.js]
external withStrong
: React.component('props) => React.component('props)
= "withStrong";
Run Code Online (Sandbox Code Playgroud)
'props
在参数和返回类型中使用type变量意味着我们将它们约束为相同。也就是说,返回的组件将具有与传入的组件完全相同的道具,在这种情况下,这正是我们想要的。
绑定本身就是所有这些。我们现在可以像这样使用它:
let strongMessage = withStrong(HelloMessage.make);
Run Code Online (Sandbox Code Playgroud)
不幸的是,这不支持JSX。要按strongMessage
原样渲染,我们必须编写类似
React.createElementVariadic(strongMessage, { "name": "Joe" }, [||]);
Run Code Online (Sandbox Code Playgroud)
不是很好。因此,让我们对其进行修复。
<StrongMessage name="Joe" />
Run Code Online (Sandbox Code Playgroud)
转换为
React.createElementVariadic(
StrongMessage.make,
StrongMessage.makeProps(~name="Joe", ()),
[||]
);
Run Code Online (Sandbox Code Playgroud)
因此,我们需要一个StrongMessage
具有两个功能的模块,make
并且makeProps
要符合的期望React.createElementVariadic
。make
只是组件本身,所以很简单。makeProps
是一个函数,该函数将props作为带标签的参数终止unit
(因为props可能是可选的),并返回js对象。这也恰好是这样[@bs.obj]
做的,绝不是巧合。
然后将其放在一起,我们得到:
module StrongMessage = {
let make = withStrong(HelloMessage.make);
[@bs.obj]
external makeProps
: (~name: string, unit) => {. "name" string }
= "";
}
Run Code Online (Sandbox Code Playgroud)
就是这样!好极了!
附录:快捷方式
好的,因此该makeProps
功能有点令人讨厌。幸运的是,在本例中,被包装的组件的道具与原始道具相同,这也是不必要的,因为StrongMessage.makeProps
它与相同HelloMessage.makeProps
。那我们就偷吧!现在我们有了
module StrongMessage = {
let make = withStrong(HelloMessage.make);
let makeProps = HelloMessage.makeProps;
}
Run Code Online (Sandbox Code Playgroud)
但是我们可以做得更好!通过使用,include HelloMessage
我们可以makeProps
完全删除(感谢@bloodyowl,通过@idkjs进行此操作)。
module StrongMessage = {
include HelloMessage;
let make = withStrong(make);
}
Run Code Online (Sandbox Code Playgroud)
很好,不是吗?之所以可行,是因为include HelloMessage
它将包括从中导出的所有定义,HelloMessage
例如makeProps
,make
以及其他所有内容。以这种方式包装组件时,可能正是您想要的,但是请注意,如果不是您想要的,它会从所包含的模块中导入并重新导出所有内容。
最后,一旦有了绑定和JSX,就可以像这样使用它
ReactDOMRe.renderToElementWithId(
<StrongMessage name="Joe" />,
"react-app"
);
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
108 次 |
最近记录: |