diff --git a/CHANGELOG.md b/CHANGELOG.md index 91c51a7e..2717505f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,6 +59,7 @@ - Fix issue where error messages related to non-existent props were displayed without location information https://github.com/rescript-lang/syntax/pull/730 - Fix issue where uncurried functions were incorrectly converting the type of a prop given as a default value to curried https://github.com/rescript-lang/syntax/pull/731 - Fix issue with printing async functions with locally abstract types https://github.com/rescript-lang/syntax/pull/732 +- Fix support for recursive components in JSX V4 https://github.com/rescript-lang/syntax/pull/733 #### :eyeglasses: Spec Compliance diff --git a/cli/reactjs_jsx_v4.ml b/cli/reactjs_jsx_v4.ml index 68fa27c1..b4c9ed61 100644 --- a/cli/reactjs_jsx_v4.ml +++ b/cli/reactjs_jsx_v4.ml @@ -1043,7 +1043,12 @@ let transformStructureItem ~config mapper item = in let innerExpression = Exp.apply - (Exp.ident (Location.mknoloc @@ Lident fnName)) + (Exp.ident + (Location.mknoloc + @@ Lident + (match recFlag with + | Recursive -> internalFnName + | Nonrecursive -> fnName))) ([(Nolabel, Exp.ident (Location.mknoloc @@ Lident "props"))] @ match hasForwardRef with @@ -1185,14 +1190,15 @@ let transformStructureItem ~config mapper item = | Recursive -> ( [ bindingWrapper - (Exp.let_ ~loc:emptyLoc Recursive - [ - makeNewBinding binding expression internalFnName; - Vb.mk - (Pat.var {loc = emptyLoc; txt = fnName}) - fullExpression; - ] - (Exp.ident {loc = emptyLoc; txt = Lident fnName})); + (Exp.let_ ~loc:emptyLoc Nonrecursive + [makeNewBinding binding expression internalFnName] + (Exp.let_ ~loc:emptyLoc Nonrecursive + [ + Vb.mk + (Pat.var {loc = emptyLoc; txt = fnName}) + fullExpression; + ] + (Exp.ident {loc = emptyLoc; txt = Lident fnName}))); ], None ) | Nonrecursive -> diff --git a/tests/ppx/react/expected/v4.res.txt b/tests/ppx/react/expected/v4.res.txt index b15c2592..9e709259 100644 --- a/tests/ppx/react/expected/v4.res.txt +++ b/tests/ppx/react/expected/v4.res.txt @@ -16,3 +16,55 @@ module AnotherName = { \"V4$AnotherName$anotherName" } } + +module Rec = { + type props = {} + + let rec make = { + @merlin.focus + let \"make$Internal" = (_: props) => { + make(({}: props)) + } + let make = { + let \"V4$Rec" = props => \"make$Internal"(props) + + \"V4$Rec" + } + make + } +} + +module Rec1 = { + type props = {} + + let rec make = { + @merlin.focus + let \"make$Internal" = (_: props) => { + React.null + } + let make = { + let \"V4$Rec1" = props => \"make$Internal"(props) + + \"V4$Rec1" + } + make + } +} + +module Rec2 = { + type props = {} + + let rec make = { + @merlin.focus + let \"make$Internal" = (_: props) => { + mm(({}: props)) + } + let make = { + let \"V4$Rec2" = props => \"make$Internal"(props) + + \"V4$Rec2" + } + make + } + and mm = x => make(x) +} diff --git a/tests/ppx/react/v4.res b/tests/ppx/react/v4.res index 27c6a6c6..3b128108 100644 --- a/tests/ppx/react/v4.res +++ b/tests/ppx/react/v4.res @@ -7,3 +7,25 @@ module AnotherName = { @react.component let anotherName = (~x) => React.string(x) } + +module Rec = { + @react.component + let rec make = () => { + make({}:props) + } +} + +module Rec1 = { + @react.component + let rec make = () => { + React.null + } +} + +module Rec2 = { + @react.component + let rec make = () => { + mm(({}: props)) + } + and mm = (x) => make(x) +}