Skip to content

Commit 4e434f0

Browse files
committed
refactor: create per-memo component subclasses with tag set at class level
Replace instance-level self.tag assignment with cached dynamically created ExperimentalMemoComponent subclasses via _get_experimental_memo_component_class, so the tag is a class-level attribute rather than set in _post_init.
1 parent 3642e5f commit 4e434f0

File tree

3 files changed

+29
-5
lines changed

3 files changed

+29
-5
lines changed

pyi_hashes.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,5 +119,5 @@
119119
"reflex/components/recharts/polar.pyi": "ea4743e8903365ba95bc4b653c47cc4a",
120120
"reflex/components/recharts/recharts.pyi": "b3d93d085d51053bbb8f65326f34a299",
121121
"reflex/components/sonner/toast.pyi": "636050fcc919f8ab0903c30dceaa18f1",
122-
"reflex/experimental/memo.pyi": "50be0b7fe796412f60f3bd1ead3f829a"
122+
"reflex/experimental/memo.pyi": "78b1968972194785f72eab32476bc61d"
123123
}

reflex/experimental/memo.py

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import dataclasses
66
import inspect
77
from collections.abc import Callable
8-
from functools import update_wrapper
8+
from functools import cache, update_wrapper
99
from typing import Any, get_args, get_origin, get_type_hints
1010

1111
from reflex import constants
@@ -103,8 +103,6 @@ def _post_init(self, **kwargs):
103103

104104
super()._post_init(**kwargs)
105105

106-
self.tag = definition.export_name
107-
108106
props: dict[str, Any] = {}
109107
for key, value in {**declared_props, **rest_props}.items():
110108
camel_cased_key = format.to_camel_case(key)
@@ -116,6 +114,28 @@ def _post_init(self, **kwargs):
116114
object.__setattr__(self, "get_props", lambda: prop_names)
117115

118116

117+
@cache
118+
def _get_experimental_memo_component_class(
119+
export_name: str,
120+
) -> type[ExperimentalMemoComponent]:
121+
"""Get the component subclass for an experimental memo export.
122+
123+
Args:
124+
export_name: The exported React component name.
125+
126+
Returns:
127+
A cached component subclass with the tag set at class definition time.
128+
"""
129+
return type(
130+
f"ExperimentalMemoComponent_{export_name}",
131+
(ExperimentalMemoComponent,),
132+
{
133+
"__module__": __name__,
134+
"tag": export_name,
135+
},
136+
)
137+
138+
119139
EXPERIMENTAL_MEMOS: dict[str, ExperimentalMemoDefinition] = {}
120140

121141

@@ -877,7 +897,7 @@ def __call__(self, *children: Any, **props: Any) -> ExperimentalMemoComponent:
877897
raise TypeError(msg)
878898

879899
# Build the component props passed into the memo wrapper.
880-
return ExperimentalMemoComponent._create(
900+
return _get_experimental_memo_component_class(definition.export_name)._create(
881901
children=list(children),
882902
memo_definition=definition,
883903
**explicit_values,

tests/units/experimental/test_memo.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,14 @@ def my_card(
8282
foo="extra",
8383
class_name="extra",
8484
)
85+
component_again = my_card(title="World")
8586

8687
assert isinstance(component, ExperimentalMemoComponent)
8788
assert len(component.children) == 2
8889
assert component.get_props() == ("title", "foo")
90+
assert type(component) is type(component_again)
91+
assert type(component).tag == "MyCard"
92+
assert type(component).get_fields()["tag"].default == "MyCard"
8993

9094
rendered = component.render()
9195
assert rendered["name"] == "MyCard"

0 commit comments

Comments
 (0)