Quantcast
Channel: ReScript Forum - Latest posts
Viewing all articles
Browse latest Browse all 2592

Even more JSX customization

$
0
0

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.componentWithProps don’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)?


Viewing all articles
Browse latest Browse all 2592

Trending Articles