Skip to content

Commit

Permalink
fix recursive UI (#4599)
Browse files Browse the repository at this point in the history
* fix recursive UI

* get it right pyright

* dang it darglint
  • Loading branch information
adhami3310 authored Jan 7, 2025
1 parent 880975a commit 0ad0a84
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 16 deletions.
5 changes: 4 additions & 1 deletion reflex/components/base/bare.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,14 @@ def _render(self) -> Tag:
return Tagless(contents=f"{{{self.contents!s}}}")
return Tagless(contents=str(self.contents))

def _get_vars(self, include_children: bool = False) -> Iterator[Var]:
def _get_vars(
self, include_children: bool = False, ignore_ids: set[int] | None = None
) -> Iterator[Var]:
"""Walk all Vars used in this component.
Args:
include_children: Whether to include Vars from children.
ignore_ids: The ids to ignore.
Yields:
The contents if it is a Var, otherwise nothing.
Expand Down
39 changes: 26 additions & 13 deletions reflex/components/component.py
Original file line number Diff line number Diff line change
Expand Up @@ -1020,18 +1020,22 @@ def _get_vars_from_event_triggers(
event_args.append(spec)
yield event_trigger, event_args

def _get_vars(self, include_children: bool = False) -> list[Var]:
def _get_vars(
self, include_children: bool = False, ignore_ids: set[int] | None = None
) -> Iterator[Var]:
"""Walk all Vars used in this component.
Args:
include_children: Whether to include Vars from children.
ignore_ids: The ids to ignore.
Returns:
Yields:
Each var referenced by the component (props, styles, event handlers).
"""
vars = getattr(self, "__vars", None)
ignore_ids = ignore_ids or set()
vars: List[Var] | None = getattr(self, "__vars", None)
if vars is not None:
return vars
yield from vars
vars = self.__vars = []
# Get Vars associated with event trigger arguments.
for _, event_vars in self._get_vars_from_event_triggers(self.event_triggers):
Expand Down Expand Up @@ -1075,12 +1079,15 @@ def _get_vars(self, include_children: bool = False) -> list[Var]:
# Get Vars associated with children.
if include_children:
for child in self.children:
if not isinstance(child, Component):
if not isinstance(child, Component) or id(child) in ignore_ids:
continue
child_vars = child._get_vars(include_children=include_children)
ignore_ids.add(id(child))
child_vars = child._get_vars(
include_children=include_children, ignore_ids=ignore_ids
)
vars.extend(child_vars)

return vars
yield from vars

def _event_trigger_values_use_state(self) -> bool:
"""Check if the values of a component's event trigger use state.
Expand Down Expand Up @@ -1811,19 +1818,25 @@ def get_prop_vars(self) -> List[Var]:
for name, prop in self.props.items()
]

def _get_vars(self, include_children: bool = False) -> list[Var]:
def _get_vars(
self, include_children: bool = False, ignore_ids: set[int] | None = None
) -> Iterator[Var]:
"""Walk all Vars used in this component.
Args:
include_children: Whether to include Vars from children.
ignore_ids: The ids to ignore.
Returns:
Yields:
Each var referenced by the component (props, styles, event handlers).
"""
return (
super()._get_vars(include_children=include_children)
+ [prop for prop in self.props.values() if isinstance(prop, Var)]
+ self.get_component(self)._get_vars(include_children=include_children)
ignore_ids = ignore_ids or set()
yield from super()._get_vars(
include_children=include_children, ignore_ids=ignore_ids
)
yield from filter(lambda prop: isinstance(prop, Var), self.props.values())
yield from self.get_component(self)._get_vars(
include_children=include_children, ignore_ids=ignore_ids
)

@lru_cache(maxsize=None) # noqa
Expand Down
8 changes: 6 additions & 2 deletions reflex/components/el/elements/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,8 +250,12 @@ def _get_form_refs(self) -> Dict[str, Any]:
)
return form_refs

def _get_vars(self, include_children: bool = True) -> Iterator[Var]:
yield from super()._get_vars(include_children=include_children)
def _get_vars(
self, include_children: bool = True, ignore_ids: set[int] | None = None
) -> Iterator[Var]:
yield from super()._get_vars(
include_children=include_children, ignore_ids=ignore_ids
)
yield from self._get_form_refs().values()

def _exclude_props(self) -> list[str]:
Expand Down

0 comments on commit 0ad0a84

Please sign in to comment.