-
Notifications
You must be signed in to change notification settings - Fork 47.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Babel Transform JSX to React.jsx/React.jsxDEV Plugin #16432
Conversation
React: size: 0.0%, gzip: 0.0% Details of bundled changes.Comparing: c1d3f7f...765ea44 react
Generated by 🚫 dangerJS |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is so awesome! Thanks for working on this. Left lots of comments, but mostly about the auto-import stuff. This can definitely be incrementally added later, but is a pretty cool feature to have, so let me know what you're thinking!
I reviewed this code assuming that you copied the existing transform for createElement over and with almost no experience reading babel-transform code, so the transform itself is definitely the thing I spent the least amount of time on. Definitely could have missed opportunities for improvement there.
|
||
exports[`transform react to jsx React.fragment to set keys and source 1`] = ` | ||
"var _jsxFileName = \\"\\"; | ||
var x = React.jsxDEV(React.Fragment, {}, \\"foo\\", true, { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One thing that this doesn't cover is the auto-import portion of the proposal. This is (arguably) the most challenging part of the transform because it's certainly stateful, but it would be nice to have!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, planning on adding that soon! I wanted to incrementally land these changes first though. LMK what you think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm fine with incrementally adding these features for sure. If that's the plan then I think this PR looks good as it stands.
packages/react-jsx-babel-plugin/__tests__/__snapshots__/transform-jsx-to-react-jsx-test.js.snap
Outdated
Show resolved
Hide resolved
});" | ||
`; | ||
|
||
exports[`transform react to jsx fragment with no children 1`] = `"var x = React.jsx(React.Fragment, {});"`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sebmarkbage how do you feel about auto-import of other React
namespace values? It's not discussed in the RFC but I think it should be auto-imported as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It wouldn't make sense if expected that to increase in scope. Fragment syntax is probably the only one that has special syntax so that makes sense.
<></>
should auto-import.
It should not extend to things with identifiers though.
However, for example <Fragment />
and <Profiler />
shouldn't auto-import these names into scope.
packages/react-jsx-babel-plugin/__tests__/__snapshots__/transform-jsx-to-react-jsx-test.js.snap
Outdated
Show resolved
Hide resolved
packages/react-jsx-babel-plugin/__tests__/transform-jsx-to-react-createElement-test.js
Outdated
Show resolved
Hide resolved
packages/react-jsx-babel-plugin/__tests__/transform-jsx-to-react-createElement-test.js
Outdated
Show resolved
Hide resolved
packages/react-jsx-babel-plugin/__tests__/transform-jsx-to-react-jsx-test.js
Outdated
Show resolved
Hide resolved
packages/react-jsx-babel-plugin/src/TransformJSXToReactBabelPlugin.js
Outdated
Show resolved
Hide resolved
packages/react-jsx-babel-plugin/src/TransformJSXToReactBabelPlugin.js
Outdated
Show resolved
Hide resolved
packages/react-jsx-babel-plugin/src/TransformJSXToReactBabelPlugin.js
Outdated
Show resolved
Hide resolved
packages/react-jsx-babel-plugin/src/TransformJSXToReactBabelPlugin.js
Outdated
Show resolved
Hide resolved
packages/react-jsx-babel-plugin/src/TransformJSXToReactBabelPlugin.js
Outdated
Show resolved
Hide resolved
packages/react-jsx-babel-plugin/src/TransformJSXToReactBabelPlugin.js
Outdated
Show resolved
Hide resolved
packages/react-jsx-babel-plugin/src/TransformJSXToReactBabelPlugin.js
Outdated
Show resolved
Hide resolved
packages/react-jsx-babel-plugin/src/TransformJSXToReactBabelPlugin.js
Outdated
Show resolved
Hide resolved
packages/react-jsx-babel-plugin/src/TransformJSXToReactBabelPlugin.js
Outdated
Show resolved
Hide resolved
packages/react-jsx-babel-plugin/src/TransformJSXToReactBabelPlugin.js
Outdated
Show resolved
Hide resolved
packages/react-jsx-babel-plugin/src/TransformJSXToReactBabelPlugin.js
Outdated
Show resolved
Hide resolved
packages/react-jsx-babel-plugin/src/TransformJSXToReactBabelPlugin.js
Outdated
Show resolved
Hide resolved
packages/react-jsx-babel-plugin/src/TransformJSXToReactBabelPlugin.js
Outdated
Show resolved
Hide resolved
packages/react-jsx-babel-plugin/src/TransformJSXToReactBabelPlugin.js
Outdated
Show resolved
Hide resolved
packages/react-jsx-babel-plugin/src/TransformJSXToReactBabelPlugin.js
Outdated
Show resolved
Hide resolved
packages/react-jsx-babel-plugin/src/TransformJSXToReactBabelPlugin.js
Outdated
Show resolved
Hide resolved
@jridgewell and @Jessidhia Thanks for the code review! Most of this code is forked from @babel/plugin-transform-react-jsx and associated helper. This code is for experimentation purposes only. We plan to upstream these changes to Babel at some point in the future once we've proven out the concept, and making too many deviations from the original transform would make this process harder. However, you can modify the original transform with your proposed changes if you would like! |
👍 . If the intention is to upstream these changes, we can wait to do a full review until then. |
This babel transform is a fork of the @babel/plugin-transform-react-jsx transform and is for experimentation purposes only. We don't plan to own this code in the future, and we will upstream this to Babel at some point once we've proven out the concept.
As per the RFC to simplify element creation, we want to change the JSX transform from targeting
React.createElement(type, props, children)
toReact.jsx(type, props, key)
. This modifies the existing@babel/plugin-transform-react-jsx
(and helper) babel plugin to supportReact.jsx
andReact.jsxDEV
.The main differences between
React.jsx
/React.jsxDEV
andReact.createElement
are:1.)
key
is now passed as an explicit argument rather than through props3.)
children
are now passed through props rather than as an explicit argument4.)
props
must always be an object5.)
__source
and and__self
are now passed as separate arguments intoReact.jsxDEV
rather than through propsPart of the rationale for this change is that we want to deprecate key spread through props because this is an expensive dynamic comparison operation. We want users instead always explicitly pass key as a prop. However, in the interim, we need a way to distinguish between
<div {...props} key={foo} />
and<div key={foo} {...props} />
. Therefore, until we completely deprecate key spreading, we will useReact.createElement
to transform<div {...props} key="Hi" />
andReact.jsx
to transform everything else.