Skip to content

Commit f4d5298

Browse files
authored
React fragment's children type change and JSX4 adaptation (#6238)
* add tests * fix JSX to adopt to change of React.fragment type * artifacts * Revert "artifacts" This reverts commit 649a0f7. * stale comment
1 parent 8bac19e commit f4d5298

File tree

7 files changed

+97
-26
lines changed

7 files changed

+97
-26
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
- Remove unnecessary require and import statements when using dynamic imports. https://github.com/rescript-lang/rescript-compiler/pull/6232
2222
- Fix option unboxing logic in the presence of untagged variants. https://github.com/rescript-lang/rescript-compiler/pull/6233
2323
- Fix printing of local module with type. https://github.com/rescript-lang/rescript-compiler/issues/6212
24+
- Adapting JSX4 to React.fragment's children type change (`'children` -> `React.element`) https://github.com/rescript-lang/rescript-compiler/pull/6238
2425

2526
#### :nail_care: Polish
2627

docs/JSXV4.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ function has the name of the enclosing module/file.
358358
// is transformed to
359359
360360
// v4
361-
ReactDOMRe.createElement(ReasonReact.fragment, [comp1, comp2, comp3])
361+
React.createElement(React.fragment, {children: [comp1, comp2, comp3]})
362362
363363
// v4 @ new jsx transform
364364
React.jsxs(React.jsxFragment, {children: [comp1, comp2, comp3]})

jscomp/syntax/src/reactjs_jsx_v4.ml

+34-16
Original file line numberDiff line numberDiff line change
@@ -1360,26 +1360,40 @@ let expr ~config mapper expression =
13601360
let recordOfChildren children =
13611361
Exp.record [(Location.mknoloc (Lident "children"), children)] None
13621362
in
1363-
let args =
1364-
[
1365-
(nolabel, fragment);
1366-
(match config.mode with
1367-
| "automatic" -> (
1368-
( nolabel,
1369-
match childrenExpr with
1370-
| {pexp_desc = Pexp_array children} -> (
1371-
match children with
1372-
| [] -> emptyRecord ~loc:Location.none
1373-
| [child] -> recordOfChildren child
1374-
| _ -> recordOfChildren childrenExpr)
1375-
| _ -> recordOfChildren childrenExpr ))
1376-
| "classic" | _ -> (nolabel, childrenExpr));
1377-
]
1363+
let applyReactArray expr =
1364+
Exp.apply
1365+
(Exp.ident
1366+
{txt = Ldot (Lident "React", "array"); loc = Location.none})
1367+
[(Nolabel, expr)]
13781368
in
13791369
let countOfChildren = function
13801370
| {pexp_desc = Pexp_array children} -> List.length children
13811371
| _ -> 0
13821372
in
1373+
let transformChildrenToProps childrenExpr =
1374+
match childrenExpr with
1375+
| {pexp_desc = Pexp_array children} -> (
1376+
match children with
1377+
| [] -> emptyRecord ~loc:Location.none
1378+
| [child] -> recordOfChildren child
1379+
| _ -> (
1380+
match config.mode with
1381+
| "automatic" -> recordOfChildren @@ applyReactArray childrenExpr
1382+
| "classic" | _ -> emptyRecord ~loc:Location.none))
1383+
| _ -> (
1384+
match config.mode with
1385+
| "automatic" -> recordOfChildren @@ applyReactArray childrenExpr
1386+
| "classic" | _ -> emptyRecord ~loc:Location.none)
1387+
in
1388+
let args =
1389+
(nolabel, fragment)
1390+
:: (nolabel, transformChildrenToProps childrenExpr)
1391+
::
1392+
(match config.mode with
1393+
| "classic" when countOfChildren childrenExpr > 1 ->
1394+
[(nolabel, childrenExpr)]
1395+
| _ -> [])
1396+
in
13831397
Exp.apply
13841398
~loc (* throw away the [@JSX] attribute and keep the others, if any *)
13851399
~attrs:nonJSXAttributes
@@ -1390,7 +1404,11 @@ let expr ~config mapper expression =
13901404
Exp.ident ~loc {loc; txt = Ldot (Lident "React", "jsxs")}
13911405
else Exp.ident ~loc {loc; txt = Ldot (Lident "React", "jsx")}
13921406
| "classic" | _ ->
1393-
Exp.ident ~loc {loc; txt = Ldot (Lident "ReactDOM", "createElement")})
1407+
if countOfChildren childrenExpr > 1 then
1408+
Exp.ident ~loc
1409+
{loc; txt = Ldot (Lident "React", "createElementVariadic")}
1410+
else
1411+
Exp.ident ~loc {loc; txt = Ldot (Lident "React", "createElement")})
13941412
args)
13951413
(* Delegate to the default mapper, a deep identity traversal *)
13961414
| e -> default_mapper.expr mapper e
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,59 @@
11
@@jsxConfig({version: 4, mode: "classic"})
22

3-
let _ = ReactDOM.createElement(React.fragment, [])
4-
let _ = ReactDOM.createElement(React.fragment, [ReactDOM.createDOMElementVariadic("div", [])])
5-
let _ = ReactDOM.createElement(React.fragment, [ReactDOM.createElement(React.fragment, [])])
3+
let _ = React.createElement(React.fragment, {})
4+
let _ = React.createElement(
5+
React.fragment,
6+
{children: ReactDOM.createDOMElementVariadic("div", [])},
7+
)
8+
let _ = React.createElementVariadic(
9+
React.fragment,
10+
{},
11+
[ReactDOM.createDOMElementVariadic("div", []), ReactDOM.createDOMElementVariadic("div", [])],
12+
)
13+
let _ = React.createElement(React.fragment, {children: React.createElement(React.fragment, {})})
614
let _ = React.createElement(Z.make, {})
715
let _ = React.createElement(Z.make, {children: ReactDOM.createDOMElementVariadic("div", [])})
16+
let _ = React.createElement(
17+
Z.make,
18+
{a: "a", children: ReactDOM.createDOMElementVariadic("div", [])},
19+
)
20+
let _ = React.createElementVariadic(
21+
Z.make,
22+
{children: React.null},
23+
[ReactDOM.createDOMElementVariadic("div", []), ReactDOM.createDOMElementVariadic("div", [])],
24+
)
825
let _ = ReactDOM.createDOMElementVariadic("div", [])
926
let _ = ReactDOM.createDOMElementVariadic("div", [ReactDOM.createDOMElementVariadic("div", [])])
27+
let _ = ReactDOM.createDOMElementVariadic(
28+
"div",
29+
~props={id: "id"},
30+
[ReactDOM.createDOMElementVariadic("div", [])],
31+
)
32+
let _ = ReactDOM.createDOMElementVariadic(
33+
"div",
34+
[ReactDOM.createDOMElementVariadic("div", []), ReactDOM.createDOMElementVariadic("div", [])],
35+
)
1036

1137
@@jsxConfig({version: 4, mode: "automatic"})
1238

1339
let _ = React.jsx(React.jsxFragment, {})
1440
let _ = React.jsx(React.jsxFragment, {children: ReactDOM.jsx("div", {})})
41+
let _ = React.jsxs(
42+
React.jsxFragment,
43+
{children: React.array([ReactDOM.jsx("div", {}), ReactDOM.jsx("div", {})])},
44+
)
1545
let _ = React.jsx(React.jsxFragment, {children: React.jsx(React.jsxFragment, {})})
1646
let _ = React.jsx(Z.make, {})
1747
let _ = React.jsx(Z.make, {children: ReactDOM.jsx("div", {})})
48+
let _ = React.jsx(Z.make, {a: "a", children: ReactDOM.jsx("div", {})})
49+
let _ = React.jsxs(
50+
Z.make,
51+
{children: React.array([ReactDOM.jsx("div", {}), ReactDOM.jsx("div", {})])},
52+
)
1853
let _ = ReactDOM.jsx("div", {})
1954
let _ = ReactDOM.jsx("div", {children: ?ReactDOM.someElement(ReactDOM.jsx("div", {}))})
55+
let _ = ReactDOM.jsx("div", {id: "id", children: ?ReactDOM.someElement(ReactDOM.jsx("div", {}))})
56+
let _ = ReactDOM.jsxs(
57+
"div",
58+
{children: React.array([ReactDOM.jsx("div", {}), ReactDOM.jsx("div", {})])},
59+
)

jscomp/syntax/tests/ppx/react/expected/noPropsWithKey.res.txt

+4-3
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@ module V4C = {
2222
type props = {}
2323

2424
let make = (_: props) =>
25-
ReactDOM.createElement(
25+
React.createElementVariadic(
2626
React.fragment,
27+
{},
2728
[
2829
JsxPPXReactSupport.createElementWithKey(~key="k", V4CA.make, {}),
2930
JsxPPXReactSupport.createElementWithKey(~key="k", V4CB.make, {}),
@@ -63,10 +64,10 @@ module V4C = {
6364
React.jsxs(
6465
React.jsxFragment,
6566
{
66-
children: [
67+
children: React.array([
6768
React.jsxKeyed(V4CA.make, {}, ~key="k", ()),
6869
React.jsxKeyed(V4CB.make, {}, ~key="k", ()),
69-
],
70+
]),
7071
},
7172
)
7273
let make = {

jscomp/syntax/tests/ppx/react/expected/removedKeyProp.res.txt

+3-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ module Foo = {
1414
module HasChildren = {
1515
type props<'children> = {children: 'children}
1616

17-
let make = ({children, _}: props<_>) => ReactDOM.createElement(React.fragment, [children])
17+
let make = ({children, _}: props<_>) => React.createElement(React.fragment, {children: children})
1818
let make = {
1919
let \"RemovedKeyProp$HasChildren" = (props: props<_>) => make(props)
2020

@@ -24,8 +24,9 @@ module HasChildren = {
2424
type props = {}
2525

2626
let make = (_: props) =>
27-
ReactDOM.createElement(
27+
React.createElementVariadic(
2828
React.fragment,
29+
{},
2930
[
3031
JsxPPXReactSupport.createElementWithKey(~key="k", Foo.make, {x: "x", y: "y"}),
3132
React.createElement(Foo.make, {x: "x", y: "y"}),

jscomp/syntax/tests/ppx/react/fragment.res

+11-1
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,28 @@
22

33
let _ = <></>
44
let _ = <><div /></>
5+
let _ = <><div /><div /></>
56
let _ = <><></></>
67
let _ = <Z />
78
let _ = <Z><div /></Z>
9+
let _ = <Z a="a"><div /></Z>
10+
let _ = <Z><div /><div /></Z>
811
let _ = <div />
912
let _ = <div><div /></div>
13+
let _ = <div id="id"><div /></div>
14+
let _ = <div><div /><div /></div>
1015

1116
@@jsxConfig({version:4, mode: "automatic"})
1217

1318
let _ = <></>
1419
let _ = <><div /></>
20+
let _ = <><div /><div /></>
1521
let _ = <><></></>
1622
let _ = <Z />
1723
let _ = <Z><div /></Z>
24+
let _ = <Z a="a"><div /></Z>
25+
let _ = <Z><div /><div /></Z>
1826
let _ = <div />
19-
let _ = <div><div /></div>
27+
let _ = <div><div /></div>
28+
let _ = <div id="id"><div /></div>
29+
let _ = <div><div /><div /></div>

0 commit comments

Comments
 (0)