From 26a15aa38bf8555142b980673c84b6433853f335 Mon Sep 17 00:00:00 2001 From: Florian Verdonck Date: Fri, 21 Feb 2025 09:07:23 +0000 Subject: [PATCH] @react.componentWithProps with use memo (#7300) * Exploring problem space * Copy attributes from function * Remove moved attributes from expr * Update test * Add changelog entry --- CHANGELOG.md | 1 + compiler/syntax/src/jsx_v4.ml | 7 +++++++ .../ppx/react/expected/sharedPropsWithProps.res.txt | 12 ++++++++++++ .../data/ppx/react/sharedPropsWithProps.res | 10 ++++++++++ tests/tests/src/alias_default_value_test.mjs | 10 ++++++++++ tests/tests/src/alias_default_value_test.res | 11 +++++++++++ 6 files changed, 51 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 67dcfc7a42..2f69c553eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,7 @@ - Fix runtime type check for Object in untagged variants when one variant case is `null`. https://github.com/rescript-lang/rescript/pull/7303 - Fix files that were being truncated when sent to the CDN over FTP. https://github.com/rescript-lang/rescript/pull/7306 - Fix better editor completion for applications. https://github.com/rescript-lang/rescript/pull/7291 +- Fix @react.componentWithProps no longer works with @directive("'use memo'"). https://github.com/rescript-lang/rescript/pull/7300 #### :house: Internal diff --git a/compiler/syntax/src/jsx_v4.ml b/compiler/syntax/src/jsx_v4.ml index fcf2272153..b1eb169b84 100644 --- a/compiler/syntax/src/jsx_v4.ml +++ b/compiler/syntax/src/jsx_v4.ml @@ -1244,6 +1244,7 @@ let map_binding ~config ~empty_loc ~pstr_loc ~file_name ~rec_flag binding = let wrapper_expr = Exp.fun_ ~arity:None Nolabel None props_pattern + ~attrs:binding.pvb_expr.pexp_attributes (Jsx_common.async_component ~async:is_async (Exp.apply (Exp.ident @@ -1282,6 +1283,12 @@ let map_binding ~config ~empty_loc ~pstr_loc ~file_name ~rec_flag binding = { binding with pvb_attributes = binding.pvb_attributes |> List.filter other_attrs_pure; + pvb_expr = + { + binding.pvb_expr with + (* moved to wrapper_expr *) + pexp_attributes = []; + }; }, new_binding ) else (None, binding, None) diff --git a/tests/syntax_tests/data/ppx/react/expected/sharedPropsWithProps.res.txt b/tests/syntax_tests/data/ppx/react/expected/sharedPropsWithProps.res.txt index 03dfa09891..f0e4dd013d 100644 --- a/tests/syntax_tests/data/ppx/react/expected/sharedPropsWithProps.res.txt +++ b/tests/syntax_tests/data/ppx/react/expected/sharedPropsWithProps.res.txt @@ -131,3 +131,15 @@ module V4A6 = { \"SharedPropsWithProps$V4A6" } } + +module V4A7 = { + type props = {count: int} + + let make = props => { + React.int(props.count) + } + let make = { + let \"SharedPropsWithProps$V4A7" = @directive("'use memo'") props => make(props) + \"SharedPropsWithProps$V4A7" + } +} diff --git a/tests/syntax_tests/data/ppx/react/sharedPropsWithProps.res b/tests/syntax_tests/data/ppx/react/sharedPropsWithProps.res index 00d382bc92..95acd39625 100644 --- a/tests/syntax_tests/data/ppx/react/sharedPropsWithProps.res +++ b/tests/syntax_tests/data/ppx/react/sharedPropsWithProps.res @@ -91,3 +91,13 @@ module V4A6 = { } } } + +module V4A7 = { + type props = {count: int} + + @react.componentWithProps + let make = @directive("'use memo'") + props => { + React.int(props.count) + } +} diff --git a/tests/tests/src/alias_default_value_test.mjs b/tests/tests/src/alias_default_value_test.mjs index 434e2b9763..f525661bb8 100644 --- a/tests/tests/src/alias_default_value_test.mjs +++ b/tests/tests/src/alias_default_value_test.mjs @@ -82,6 +82,15 @@ let C7 = { make: Alias_default_value_test$C7 }; +function Alias_default_value_test$C8(props) { + 'use memo'; + return props.count; +} + +let C8 = { + make: Alias_default_value_test$C8 +}; + export { C0, C1, @@ -90,5 +99,6 @@ export { C4, C6, C7, + C8, } /* No side effect */ diff --git a/tests/tests/src/alias_default_value_test.res b/tests/tests/src/alias_default_value_test.res index 1ebe9f00fa..2ed6dfc4b1 100644 --- a/tests/tests/src/alias_default_value_test.res +++ b/tests/tests/src/alias_default_value_test.res @@ -64,3 +64,14 @@ module C7 = { React.string(`Hello ${name}, you clicked me ` ++ times) } } + +module C8 = { + type props = {count: int} + + @react.componentWithProps + let make = + @directive("'use memo'") + props => { + React.int(props.count) + } +}