While experimenting with mithriljs, I was curious if I could use it in rescript (with jsx support) as well.
So I started a new project, added a JSX module and implemented all necessary types and functions.
Example of a mithril component in js:
const Component = (vnode) => {
console.log(vnode.attrs.message);
return {
view: vnode => <div>{vnode.attrs.message}</div>
};
};
I encountered some problems, but its difficult to explain or to show code because I tried a lot. But here are some of them:
- (By default) rescript expects components to be functions with a single parameter (props) which will return jsx.
- With some type gymnastics, I can write my components, but I can’t force to make all components have this shape.
-
@jsx.component/@jsx.componentWithPropsdon’t work on different shapes.
-
Jsx.elements can’t have a type parameter, so it’s not easy to type the vnode parameter to have the same type as in the view function.
(type rec element<'props> = {view: 'props => element<'props>})
Here is my current rescript solution. It compiles, but
- I could also define components, which just return jsx and they will crash at runtime.
- I have to specify the types of my make functions explicitly or I need these helper functions.
- I need an empty record type for components without props. Otherwise I get this error: “Empty record literal {} should be type annotated or used in a record context.”.
// M.res
type noProps = {}
type vnode<'props> = {attrs: 'props}
type comp<'props> = {view: vnode<'props> => Jsx.element}
let component = (options: vnode<noProps> => comp<noProps>): (noProps => Jsx.element) => {
Obj.magic(options)
}
let componentP = (options: vnode<'props> => comp<'props>): ('props => Jsx.element) => {
Obj.magic(options)
}
// Counter.res
type props = {initialCount: int}
let make = M.componentP(vnode => {
let count = ref(vnode.attrs.initialCount)
{
view: _vnode => {
<div>
<button onClick={_ => count.contents = count.contents + 1}>
{Jsx.string("click me")}
</button>
<span> {Jsx.int(count.contents)} </span>
</div>
},
}
})
TLDR;
It’s just an experiment. I don’t know, if I want to use mithril in any project. But I had similar problems when I was implementing some web component stuff. So my question:
What is the future of JSX in rescript?
Do you think it is feature complete?
Are the improvements in mind (looking at custom data attributes)?