diff --git a/packages/reflex-base/src/reflex_base/vars/function.py b/packages/reflex-base/src/reflex_base/vars/function.py index 812c7d72d8b..30cda3c3679 100644 --- a/packages/reflex-base/src/reflex_base/vars/function.py +++ b/packages/reflex-base/src/reflex_base/vars/function.py @@ -385,11 +385,10 @@ def to_javascript(self) -> str: Returns: The destructured argument in JavaScript. """ - return format.wrap( - ", ".join(self.fields) + (f", ...{self.rest}" if self.rest else ""), - "{", - "}", - ) + inner = ", ".join(self.fields) + if self.rest: + inner = f"{inner}, ...{self.rest}" if inner else f"...{self.rest}" + return format.wrap(inner, "{", "}") @dataclasses.dataclass( diff --git a/tests/units/experimental/test_memo.py b/tests/units/experimental/test_memo.py index 99b547551da..efb006d545d 100644 --- a/tests/units/experimental/test_memo.py +++ b/tests/units/experimental/test_memo.py @@ -160,6 +160,32 @@ def merge_styles( merge_styles(base=base, overrides={"color": "red"}) +def test_component_returning_memo_with_only_rest(): + """Component-returning memos with only RestProp should emit valid JSX (#6443).""" + + @rx._x.memo + def hover_trigger(rest: rx.RestProp) -> rx.Component: + return rx.text("hover me", rest) + + files, _ = compiler.compile_memo_components((), tuple(EXPERIMENTAL_MEMOS.values())) + code = "\n".join(c for _, c in files) + assert "memo(({...rest})" in code + assert "({," not in code + + +def test_var_returning_memo_with_only_rest(): + """Var-returning memos with only RestProp should emit valid JS (#6443).""" + + @rx._x.memo + def merge_only(overrides: rx.RestProp) -> rx.Var[Any]: + return overrides + + files, _ = compiler.compile_memo_components((), tuple(EXPERIMENTAL_MEMOS.values())) + code = "\n".join(c for _, c in files) + assert "(({...overrides}) => overrides)" in code + assert "({," not in code + + def test_var_returning_memo_with_children_and_rest(): """Var-returning memos should accept positional children plus keyword props.""" @@ -397,7 +423,7 @@ def fake_compile_single_memo_component( {"shared-lib": [ImportVar(tag=component_render["name"])]}, ) - real_merge_imports = compiler.utils.merge_imports + real_merge_imports = compiler_utils.merge_imports def reject_growing_merge(*imports): if len(imports) == 2 and imports[0]: @@ -406,7 +432,7 @@ def reject_growing_merge(*imports): return real_merge_imports(*imports) monkeypatch.setattr( - compiler.utils, + compiler_utils, "compile_experimental_component_memo", fake_compile_experimental_component_memo, ) @@ -415,7 +441,7 @@ def reject_growing_merge(*imports): "_compile_single_memo_component", fake_compile_single_memo_component, ) - monkeypatch.setattr(compiler.utils, "merge_imports", reject_growing_merge) + monkeypatch.setattr(compiler_utils, "merge_imports", reject_growing_merge) files, aggregate_imports = compiler.compile_memo_components((), memos)