3 ms·
Hi, I'm the guy who wrote this proposal. tl;dr: My proposal transforms <foo bar={qux}>bla</foo> into { [Symbol.for('jsx')]: 'foo', bar: qux, children: "bla" }
by 90s_dev 1y ago
Hi, I'm the guy who wrote this proposal.
tl;dr:
My proposal transforms <foo bar={qux}>bla</foo> into { [Symbol.for('jsx')]: 'foo', bar: qux, children: "bla" }
It's self-contained, generic, doesn't rely on imports or globals, and avoids tag key collisions. It's the only way I can imagine it ever being standardized.
I currently use JSX for:
* Creating custom GUI view objects in https://90s.dev/os/ https://90s.dev/os/
* Using JSX as a convenient & composable string-builder in Node.js via https://immaculata.dev/ https://immaculata.dev/ when generating all my sites at build-time e.g. https://github.com/sdegutis/immaculata.dev/blob/main/site/template/core.tsx https://github.com/sdegutis/immaculata.dev/blob/main/site/te...
* Using JSX to generate plain DOM objects in the browser in some of my sites like https://github.com/sdegutis/minigamemaker.com/blob/main/site/app.tsx#L29-L36 https://github.com/sdegutis/minigamemaker.com/blob/main/site...
- WorldMaker 1y agoI think it is still useful as a function call syntax. There's a variety of data structures that people convert JSX to already, including direct-to-DOM. Choosing a blessed one seems harder than a function calling convention, and a function calling convention resembles other language things like tagged templates. I agree that the current "auto-imports" to find that function are nonsense and far too React specific. But the current "global" approach isn't actually "require a global" it is "requires a variable in scope" so it works with "Bring-Your-Own-Import" just fine. We just need a better standard for what that BYOI function is called by default. `React.createElement` is obviously silly. I've been happy in my own projects standardizing on `jsx` as the function name. (It resembles the auto-imports, too, even if I still don't understand why React thought it needed an extra underscore.) I think the biggest tweak that would be nice if we are also wishing for ponies would be a way to set that function per block of JSX like the way that you can tag a template. That would make it far easier than the current per-file or per-project configurations. jsx<foo bar={qux}><zoot>bla</zoot></foo> That doesn't look terrible. Not great either. But I'm sure the big problem with it is that it makes the `jsx < foo` less than versus `jsx<foo />` tag parsing a lot harder. ETA: New idea, what if it was a fake dot tag .< operator? jsx.<foo bar={qux}><zoot>bla</zoot></foo> react.<foo bar={qux}><zoot>bla</zoot></foo> snabbdom.<foo bar={qux}><zoot>bla</zoot></foo> Maybe?
- 90s_dev 1y agoIf it's just a variable in scope, you could do: if (condition) { // new scope const jsx = // ... return <foo/> } In practice, "variable in scope" is essentially the same as "global in scope" and React used to require you to import 'react' at the top of every JSX file for this reason. Your solution is tantamount to just changing that to import jsx from 'react' but still requiring it explicitly. The main problem with this is that it's non-trivial to make sure variables are in scope before/while loading a file, and they should be loaded on an as-needed basis instead of always, which is what inevitably ends up happening when you need React classic, you import React at the top of every HTML file. These problems seem to be what led to auto-imports. I admit that my solution still does require you do something like import interpretJsx from 'something', and even further it requires you to manually call interpretJsx(<foo/>) which can be tedious and verbose. The main benefit is that at least it becomes a standard. And besides, we probably won't need to call those functions everywhere, just at the top of a tree, like the same place you call React.render(root) The main downside is lack of monomorphism, especially if you're passing an entire tree to interpretJsx(). I admit this is not solved by my proposal. But I still wanted to put the proposal out before smarter eyes than mine anyway.
- WorldMaker 1y agoA problem with going straight to objects is you potentially create a lot of GC churn if the `interpretJsx()` converts it to a different data structure. Also because it is a tree structure, you are probably talking a recursive depth-first-search or other tree-walker algorithm that can easily blow up the stack while it works. If you are doing something Virtual DOM-like and evaluating lots of trees, that memory/GC and CPU churn compound quickly. This is part of why JSX has always been function calls rather than a data structure to interpret: the recursion to walk the tree is flattened at "compile time". I don't see why it is a problem you'd need to import your `jsx` function in every file that uses JSX syntax, but perhaps because that's how I've always preferred to use JSX, even with React. Explicit imports are better than implicit ones. If you use lit-html you have to import its `html` function everywhere to get html`` template literals to work. It's not a lot of overhead and it works well. You can add the auto-import smarts to your editor, to your snippet files and template files. Typescript already has a ton of auto-import suggestions as you write a file.