[babel-plugin-react-jsx] Avoid duplicate "children" key in props object (#17094)
* [babel-plugin-react-jsx] Avoid duplicate "children" key in props object * Use Object.assign approach
Dominic Gannaway committed
Oct 15, 2019 at 15:41 UTC
e7704e22a146c2d5b00f8c6bfa6255153272f053
3 files changed
+32
-1
packages/babel-plugin-react-jsx/__tests__/TransformJSXToReactJSX-test.js
+6
@@ -480,4 +480,10 @@ describe('transform react to jsx', () => {
480
transform(`<Component y={2} {...x} />`, {useBuiltIns: false})
481
).toMatchSnapshot();
482
});
483
+
484
+ it('should not contain duplicate children key in props object', () => {
485
+ expect(
486
+ transform(`<Component children={1}>2</Component>`)
487
+ ).toMatchSnapshot();
488
+ });
489
});
packages/babel-plugin-react-jsx/__tests__/__snapshots__/TransformJSXToReactJSX-test.js.snap
+8
@@ -250,6 +250,14 @@ var e = React.jsx(F, {
250
});
251
`;
252
253
+exports[`transform react to jsx should not contain duplicate children key in props object 1`] = `
254
+React.jsx(Component, Object.assign({
255
+ children: 1
256
+}, {
257
+ children: "2"
258
+}));
259
+`;
260
+
261
exports[`transform react to jsx should not strip nbsp even couple with other whitespace 1`] = `
262
React.jsx("div", {
263
children: "\\xA0 "
packages/babel-plugin-react-jsx/src/TransformJSXToReactBabelPlugin.js
+18
-1
@@ -268,11 +268,20 @@ You can turn on the 'throwIfNamespace' flag to bypass this warning.`,
268
);
269
}
270
271
+ function isChildrenProp(prop) {
272
+ return (
273
+ t.isJSXAttribute(prop) &&
274
+ t.isJSXIdentifier(prop.name) &&
275
+ prop.name.name === 'children'
276
+ );
277
+ }
278
+
279
// Builds props for React.jsx. This function adds children into the props
280
// and ensures that props is always an object
281
function buildJSXOpeningElementAttributes(attribs, file, children) {
282
let _props = [];
283
const objs = [];
284
+ const hasChildren = children && children.length > 0;
285
286
const useBuiltIns = file.opts.useBuiltIns || false;
287
if (typeof useBuiltIns !== 'boolean') {
@@ -287,6 +296,14 @@ You can turn on the 'throwIfNamespace' flag to bypass this warning.`,
296
if (t.isJSXSpreadAttribute(prop)) {
297
_props = pushProps(_props, objs);
298
objs.push(prop.argument);
299
+ } else if (hasChildren && isChildrenProp(prop)) {
300
+ // In order to avoid having duplicate "children" keys, we avoid
301
+ // pushing the "children" prop if we have actual children. Instead
302
+ // we put the children into a separate object and then rely on
303
+ // the Object.assign logic below to ensure the correct object is
304
+ // formed.
305
+ _props = pushProps(_props, objs);
306
+ objs.push(t.objectExpression([convertAttribute(prop)]));
307
} else {
308
_props.push(convertAttribute(prop));
309
}
@@ -294,7 +311,7 @@ You can turn on the 'throwIfNamespace' flag to bypass this warning.`,
311
312
// In React.JSX, children is no longer a separate argument, but passed in
313
// through the argument object
297
- if (children && children.length > 0) {
314
+ if (hasChildren) {
315
if (children.length === 1) {
316
_props.push(t.objectProperty(t.identifier('children'), children[0]));
317
} else {