Hi. I've searched through the various issues (as well as other places this has been discussed) and I don't see a current open issue to address the lack of custom JSX pragma support.
As discussed elsewhere, other transpilers allow specifying any function name to insert when producing hyperscript from JSX. It's worth noting that hyperscript predates React, and is a format shared by a large number of libraries entirely separate from the React project. Currently, TypeScript only allows configuration of an Object on which to invoke .createElement()
, however the original implementations and many descendants thereof simply use h()
. You can read my attempt to document some of the context and background here.
The configuration would presumably look something like this:
{
"compilerOptions": {
"jsx": "react",
"jsxPragma": "h"
}
}
... and the output would look like:
// input:
<div id="foo">hello</div>
// output:
h('div', { id:'foo' }, 'hello');
Has this been bypassed for feasibility reasons? If not, I think it would be a valuable addition.
I have a different view
consider this proposal
Proposal: Replace emitter with syntax tree transformations and a simplified node emitter.
Your requirement can be implements via " custom syntax tree transformations " . So I don't think it's necessary for us to increase tsconfig 's complexity.
And I think that's a great idea, however the tsconfig already has an option for JSX (that only supports React.) I don't see why we'd support just the first half of the function call.
@WanderWang this is very much a userland feature. Most users of TypeScript would not be compelled to extend TypeScript itself simply to account for a common use-case.
My suggestion could replace the existing "jsxNamespace"
config property, since jsxPragma
enables a superset of use-cases, while still allowing the default to remain "React.createElement"
.
Currently, TypeScript forces users to build shims for non-React JSX use-cases, which is significantly more cumbersome than needing to know about another (or a different) configuration property.
workaround:
import * as h from "someplace";
const hyper = {createElement: h}
@basarat yes, this is what people currently do. However, this is a second-class experience and difficult to explain in documentation.
@basarat that is exactly that - a workaround. It seems that there should be a better way of doing this.
No discussion, no nothing. Sad.
My use-case is to support JSX within skate.js. skatejs has a hyperscript compliant API import { h } from 'skatejs';
, so all that's missing is JSX pragma support or something equivalent.
Accepting PRs for a flag jsxFactory
which accepts a string, like "h"
or "React.createElement"
react
emit mode no longer require the React
identifier to be presentSweet, someone submit a PR
Be the PR you want to see in the world :wink:
I would, but I've never used TypeScript and already have tons to maintain 😛
I'll raise a PR.
If this flag is specified, JSX elements in react emit mode no longer require the React identifier to be present.
In the case of // @jsxFactory: a
, we _should_ require the a
identifier to be present right? Following on that // @jsxFactory: a.b
would still require just a
to be present.
I think we _should_ require React
to be present if jsxFactory: React.createElement
is used.
I also need to look into how nevermind React.__spread
should be dealt with. I hadn't realised that reactNamespace
was also used to describe which object .__spread
hangs off..__spread
is no longer used.
sounds reasonable.
I've raised the PR — https://github.com/Microsoft/TypeScript/pull/11267.
For future readers —
{
"compilerOptions": {
"jsx": "react",
"jsxFactory": "h"
}
}
The above configuration will get you going.
Edit: updated the jsxFactory property name in comment above.
@mhegazy I get this error — Unknown compiler option 'jsxFactory'
tsc --version
Version 2.1.1
Use typescript@next
.
This is awesome. Kudos for baking this as a compiler param.
<div>Hello</div>
should compile to:
({h}) => h('div', {}, 'Hello');
and them React could do:
(({h}) => h('div', {}, 'Hello'))({
h: React.createElement,
});
Most helpful comment
For future readers —
The above configuration will get you going.