mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Wrap JSXFragment in expr container for attributes
@mofeiZ noticed that some configurations of prettier don't support JSXFragment appearing as a JSXAttribute value, in violation of the spec. Coincidentally I noticed that our internal build system also fails on this as i was trying to roll out on more surfaces. This PR makes sure we wrap fragments in an expressioncontainer if they appear as jsxattribute values.
This commit is contained in:
+5
-2
@@ -1280,12 +1280,15 @@ function codegenJsxAttribute(
|
||||
let value;
|
||||
switch (innerValue.type) {
|
||||
case "StringLiteral":
|
||||
case "JSXElement":
|
||||
case "JSXFragment": {
|
||||
case "JSXElement": {
|
||||
value = innerValue;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// NOTE JSXFragment is technically allowed as an attribute value per the spec
|
||||
// but many tools do not support this case. We emit fragments wrapped in an
|
||||
// expression container for compatibility purposes.
|
||||
// spec: https://github.com/facebook/jsx/blob/main/AST.md#jsx-attributes
|
||||
value = createJsxExpressionContainer(attribute.place.loc, innerValue);
|
||||
break;
|
||||
}
|
||||
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @flow
|
||||
function Component({items}) {
|
||||
// Per the spec, <Foo value=<>{...}</> /> is valid.
|
||||
// But many tools don't allow fragments as jsx attribute values,
|
||||
// so we ensure not to emit them wrapped in an expression container
|
||||
return items.length > 0
|
||||
? (
|
||||
<Foo value={
|
||||
<>{items.map(item => <Bar key={item.id} item={item} />)}</>
|
||||
}></Foo>
|
||||
)
|
||||
: null;
|
||||
}
|
||||
|
||||
function Foo({item}) {
|
||||
return <div>{item.name}</div>;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{items: [{id: 1, name: 'One!'}]}],
|
||||
};
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { unstable_useMemoCache as useMemoCache } from "react";
|
||||
function Component(t26) {
|
||||
const $ = useMemoCache(2);
|
||||
const { items } = t26;
|
||||
const c_0 = $[0] !== items;
|
||||
let t0;
|
||||
if (c_0) {
|
||||
t0 =
|
||||
items.length > 0 ? (
|
||||
<Foo
|
||||
value={
|
||||
<>
|
||||
{items.map((item) => (
|
||||
<Bar key={item.id} item={item} />
|
||||
))}
|
||||
</>
|
||||
}
|
||||
/>
|
||||
) : null;
|
||||
$[0] = items;
|
||||
$[1] = t0;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
}
|
||||
return t0;
|
||||
}
|
||||
|
||||
function Foo(t7) {
|
||||
const $ = useMemoCache(2);
|
||||
const { item } = t7;
|
||||
const c_0 = $[0] !== item.name;
|
||||
let t0;
|
||||
if (c_0) {
|
||||
t0 = <div>{item.name}</div>;
|
||||
$[0] = item.name;
|
||||
$[1] = t0;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
}
|
||||
return t0;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{ items: [{ id: 1, name: "One!" }] }],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
// @flow
|
||||
function Component({items}) {
|
||||
// Per the spec, <Foo value=<>{...}</> /> is valid.
|
||||
// But many tools don't allow fragments as jsx attribute values,
|
||||
// so we ensure not to emit them wrapped in an expression container
|
||||
return items.length > 0
|
||||
? (
|
||||
<Foo value={
|
||||
<>{items.map(item => <Bar key={item.id} item={item} />)}</>
|
||||
}></Foo>
|
||||
)
|
||||
: null;
|
||||
}
|
||||
|
||||
function Foo({item}) {
|
||||
return <div>{item.name}</div>;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{items: [{id: 1, name: 'One!'}]}],
|
||||
};
|
||||
Reference in New Issue
Block a user