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"
);
此外,Reason Playground 上也有一个可运行的示例,只需对其进行一些修改即可解决不必要单独 JavaScript 文件的问题。
绑定
withStrong
只是一个函数。它恰好是一个接收和返回 React 组件的函数,这有点神秘,但它们像任何其他值一样。我们可以像普通函数一样绑定它。
即使是这样简单的操作也可以工作。
[@bs.module ./hoc.js]
external withStrong : 'a => 'a = "withStrong";
假设您始终确保传入组件,但是这样并不特别安全,因为您也可以传递任何其他内容,因此让我们尝试像应该使用的类型系统一样限制它,仅接受React组件。
ReasonReact源代码表示组件具有类型component('props)
,因此这就是我们将使用的内容。
[@bs.module ./hoc.js]
external withStrong
: React.component('props) => React.component('props)
= "withStrong";
在参数和返回类型中使用'props'
类型变量意味着我们将它们限制为相同。也就是说,返回的组件将与传入的组件具有完全相同的属性,这正是我们在此情况下想要的。
至于绑定本身,就是这些了。现在我们可以像这样使用它:
let strongMessage = withStrong(HelloMessage.make);
不幸的是,这不支持JSX。要像原样呈现strongMessage
,我们必须编写类似于以下内容的代码:
React.createElementVariadic(strongMessage, { "name": "Joe" }, [||]);
不太好,让我们修复它。
JSX
<StrongMessage name="Joe" />
transforms to
React.createElementVariadic(
StrongMessage.make,
StrongMessage.makeProps(~name="Joe", ()),
[||]
);
因此,我们需要一个StrongMessage模块,其中包含两个函数:make
和makeProps
,它们符合React.createElementVariadic
所期望的内容。 make
只是组件本身,所以很简单。 makeProps
是一个函数,它接受属性标签参数直到unit
为止(因为属性可能是可选的),并返回js对象。这恰好也是[@bs.obj]
所做的事情,这不是巧合。
将所有这些放在一起,我们得到:
module StrongMessage = {
let make = withStrong(HelloMessage.make);
[@bs.obj]
external makeProps
: (~name: string, unit) => {. "name" string }
= "";
}
就这样了!耶!
附录:快捷方式
好的,makeProps
函数有点啰嗦。幸运的是,在我们的情况下,包装组件的props与原始组件相同,因此它也是不必要的,因为StrongMessage.makeProps
将与HelloMessage.makeProps
相同。那我们就直接借用它吧!现在我们有:
module StrongMessage = {
let make = withStrong(HelloMessage.make);
let makeProps = HelloMessage.makeProps;
}
我们可以做得更好!通过使用include HelloMessage
,我们可以完全不使用makeProps
(感谢@bloodyowl,通过@idkjs实现)。
module StrongMessage = {
include HelloMessage;
let make = withStrong(make);
}
这很不错,对吧?这么做是因为 include HelloMessage
会包括来自 HelloMessage
的所有导出定义,例如 makeProps
,以及 make
和其他任何东西。当您以这种方式包装组件时,这可能是您想要的,但请注意,它会从所包含的模块中导入和重新导出 所有 东西,如果这不是您想要的,请小心。
用法
最后,一旦我们同时具备了绑定和JSX,我们可以像这样使用它:
ReactDOMRe.renderToElementWithId(
<StrongMessage name="Joe" />,
"react-app"
);