Change JSX output from React to SolidJs?

Note that Solid has h (hyperscript) API that can be used here instead of React API. It won’t be as fast for during setup, but after setup it should be as fast as regular Solid JSX.

Example code is something like:

const view = h('div', [
  h('p', h('span', 'Hello'))
], {style: "color: red;"})

(I didn’t verify if that works, but you get the idea).

So you can at least make it output h-compatible code. You might have to import it and re-export as createElement.

2 Likes

FYI someone got Rescript+HyperScript partially working in a gist here.

3 Likes

@Hongbo I think ReScript should be able to output the JSX, instead of React.createElement.

To more output closely output JS how it would have been hand-written in a real life setting (most if not all would use Babel to transform the JSX anyway). It improves the escape hatch to JS, since rewriting a bunch of React.createElement to JSX would be a lot of work if you decide to move back to pure JS/TS. It would have the side benefit of improving compatibility with SolidJS and other compilers that take JSX as input.

11 Likes

Hey! Just bumping this thread as I’m looking for this use case as well (ReScript + SolidJS)! I think ReScript should aim to be flexible and not rely solely on React as the only frontend framework it supports. The web moves too fast to be that strict.

11 Likes

While I would also prefer the variant, that the compiler optionally outputs JSX directly, I made a test with the proposal from @ryyppy to replace the createElement and createElementVariadic function.
And it worked pretty well.

These bindings allow the usage of solidJs in conjunction with JSX: https://github.com/Fattafatta/rescript-solidjs

You can also find a more elaborate explanation on how it actually works here github discussion.

4 Likes

This is a thread where emitting jsx directly can be explored: JSX v4 & next rescript-react 0.10.x - #12 by cristianoc

Is it correct that solidjs support would then come for free, as well as enabling a few things on react that createElement does not provide?

How about compatibility with older react versions? Is that something one should worry about?

Is there something else that direct jsx would enable supporting, besides SolidJs? If not, what else is missing, and are there opportunities to support more.

Direct JSX support is essential to SolidJS (as it applies its own JSX transform that is very different from the React JSX transform) However all the bindings should be done for sure.

Moreover, direct JSX support would also enable supporting Vue (with JSX) much smoother, and will probably make it easier for users to migrate away from ReScript :laughing:

Edit: Looks like enough amount of bindings are available in rescript-solidjs

1 Like

What are the expectations for the generated code?
jsx calls / _jsx calls, without any imports?

Or is the idea to support something like TypeScript’s jsx preserve mode?

It seems that handling JSX like the preserve option from TypeScript, is the best solution. It would enable to use Rescript without React.
Here is the docs from solids about typescript configuration.

3 Likes

I thought “direct JSX” means JSX preserve mode. If that means the new React 17 JSX transform thing, it doesn’t change anything related to SolidJS support.

2 Likes

Thanks it’s clear now.

1 Like

I’ve created an issue with a rough outline on how to explore implementing preserve mode.

This is going to be pretty much orthogonal to the ppx work on JSX, as likely this won’t run the ppx at all (unless some preparation work is required and that’s the right spot for it).

1 Like

That issue is open to contribution if someone is interested.

In terms of planning, an open question remains on what else should one consider supporting, in addition to SolidJs (and whatever else can take advantage of preserve mode).

1 Like

+1 on preserve mode. It’s the safest and most future proof bet imo. We can then specialize further as we see where the community goes with the support - is any of the other fws outside of React gaining traction with ReScript?

First class support, like for React, is very valuable because it means any ReScript project could theoretically skip using Babel. Less transforming, faster, etc. That doesn’t matter with something like SolidJs of course, where the whole SolidJs optimizer/compiler is a Babel plugin. But there might be other fws around that gain traction, that have the same characteristics as React, where first classing could be a huge performance gain. Time will tell!

7 Likes

Actually, first-class support for SolidJS is also a viable option, especially looking at other players like Bun implementing SolidJS JSX transforms natively. While I also agree that relying on the preserve option makes much more sense for now, IMO building a PPX for it will be pretty considerable one if the user group grows large enough.

3 Likes

If it’s going to be possible to use something like Bun (or maybe swc) with ReScript, maybe the pain caused by the slowness of Babel will go away anyway :slight_smile:

2 Likes

Yes, I think this is a good point too.

1 Like

After playing around with rescript-solidjs for a while I found a lot of problems with the HyperScript approach. The most notable one is that HyperScript creates all components “inside out”. The innermost components are created first. This makes it incompatible with Context (at least I didn’t get it to work).

Since Context is a central piece of solid (for example it is used in solid-app-router). It became really frustrating to use.

So I tried the approach mentioned by @mosheduminer. There was already a babel plugin to transform react backt to jsx: (Plugin. I used this as a starting point to create a transform specific for ReScript:
babel-plugin-rescript-react-to-jsx

The result works surprisingly well! So I updated rescript-solidjs to use this approach instead.

As a bonus it is no longer necessary to adapt the control flow components.They bind directly to solid now. The updated bindings are basically zero cost.

1 Like