From 7597a2f3bb68967ae231b9b2947a3e179084d33b Mon Sep 17 00:00:00 2001 From: Khaleel Al-Adhami Date: Mon, 2 Jun 2025 13:40:21 -0700 Subject: [PATCH] ignore visited components for all_app_wrap_components --- reflex/components/base/bare.py | 20 +++++++++++++++---- reflex/components/component.py | 36 ++++++++++++++++++++++++++++------ 2 files changed, 46 insertions(+), 10 deletions(-) diff --git a/reflex/components/base/bare.py b/reflex/components/base/bare.py index 5baff2d52db..3ebffe55709 100644 --- a/reflex/components/base/bare.py +++ b/reflex/components/base/bare.py @@ -141,17 +141,29 @@ def _get_all_custom_code(self) -> set[str]: custom_code |= component._get_all_custom_code() return custom_code - def _get_all_app_wrap_components(self) -> dict[tuple[int, str], Component]: + def _get_all_app_wrap_components( + self, *, ignore_ids: set[int] | None = None + ) -> dict[tuple[int, str], Component]: """Get the components that should be wrapped in the app. + Args: + ignore_ids: The ids to ignore when collecting components. + Returns: The components that should be wrapped in the app. """ - app_wrap_components = super()._get_all_app_wrap_components() + ignore_ids = ignore_ids or set() + app_wrap_components = super()._get_all_app_wrap_components( + ignore_ids=ignore_ids + ) if isinstance(self.contents, Var): for component in _components_from_var(self.contents): - if isinstance(component, Component): - app_wrap_components |= component._get_all_app_wrap_components() + component_id = id(component) + if isinstance(component, Component) and component_id not in ignore_ids: + ignore_ids.add(component_id) + app_wrap_components |= component._get_all_app_wrap_components( + ignore_ids=ignore_ids + ) return app_wrap_components def _get_all_refs(self) -> set[str]: diff --git a/reflex/components/component.py b/reflex/components/component.py index d3be5a176ef..02f4ce64914 100644 --- a/reflex/components/component.py +++ b/reflex/components/component.py @@ -1976,24 +1976,38 @@ def _get_app_wrap_components() -> dict[tuple[int, str], Component]: """ return {} - def _get_all_app_wrap_components(self) -> dict[tuple[int, str], Component]: + def _get_all_app_wrap_components( + self, *, ignore_ids: set[int] | None = None + ) -> dict[tuple[int, str], Component]: """Get the app wrap components for the component and its children. + Args: + ignore_ids: A set of component IDs to ignore. Used to avoid duplicates. + Returns: The app wrap components. """ + ignore_ids = ignore_ids or set() # Store the components in a set to avoid duplicates. components = self._get_app_wrap_components() for component in tuple(components.values()): - components.update(component._get_all_app_wrap_components()) + component_id = id(component) + if component_id in ignore_ids: + continue + ignore_ids.add(component_id) + components.update( + component._get_all_app_wrap_components(ignore_ids=ignore_ids) + ) # Add the app wrap components for the children. for child in self.children: + child_id = id(child) # Skip BaseComponent and StatefulComponent children. - if not isinstance(child, Component): + if not isinstance(child, Component) or child_id in ignore_ids: continue - components.update(child._get_all_app_wrap_components()) + ignore_ids.add(child_id) + components.update(child._get_all_app_wrap_components(ignore_ids=ignore_ids)) # Return the components. return components @@ -2206,13 +2220,23 @@ def get_component(self) -> Component: component._add_style_recursive(style) return component - def _get_all_app_wrap_components(self) -> dict[tuple[int, str], Component]: + def _get_all_app_wrap_components( + self, *, ignore_ids: set[int] | None = None + ) -> dict[tuple[int, str], Component]: """Get the app wrap components for the custom component. + Args: + ignore_ids: A set of IDs to ignore to avoid infinite recursion. + Returns: The app wrap components. """ - return self.get_component()._get_all_app_wrap_components() + ignore_ids = ignore_ids or set() + component = self.get_component() + if id(component) in ignore_ids: + return {} + ignore_ids.add(id(component)) + return self.get_component()._get_all_app_wrap_components(ignore_ids=ignore_ids) CUSTOM_COMPONENTS: dict[str, CustomComponent] = {}