Selaa lähdekoodia

Account for imports of custom components for frontend installation

Create new ImportVar that only install the package to avoid rendering the
imports in the page that contains the custom component itself.
Masen Furer 1 vuosi sitten
vanhempi
säilyke
86a1e8a07e
1 muutettua tiedostoa jossa 33 lisäystä ja 0 poistoa
  1. 33 0
      reflex/components/component.py

+ 33 - 0
reflex/components/component.py

@@ -1265,6 +1265,9 @@ class CustomComponent(Component):
     # The props of the component.
     props: Dict[str, Any] = {}
 
+    # Props that reference other components.
+    component_props: Dict[str, Component] = {}
+
     def __init__(self, *args, **kwargs):
         """Initialize the custom component.
 
@@ -1302,6 +1305,7 @@ class CustomComponent(Component):
 
                 # Track hooks and imports associated with Component instances.
                 if base_value is not None and isinstance(value, Component):
+                    self.component_props[key] = value
                     value = base_value._replace(
                         merge_var_data=VarData(  # type: ignore
                             imports=value.get_imports(),
@@ -1335,6 +1339,25 @@ class CustomComponent(Component):
         """
         return hash(self.tag)
 
+    def _get_imports(self) -> Dict[str, List[ImportVar]]:
+        """Get the imports for the component.
+
+        This is needed because otherwise the imports for the component are not
+        installed during compile time, but they are rendered into the page.
+
+        Returns:
+            The imports for the component and any custom component props.
+        """
+        return imports.merge_imports(
+            super()._get_imports(),
+            # Sweep up any imports from CustomComponent props for frontend installation.
+            {
+                library: [ImportVar(tag=None, render=False, install=True)]
+                for comp in self.get_custom_components()
+                for library in comp.get_component(comp).get_imports()
+            },
+        )
+
     @classmethod
     def get_props(cls) -> Set[str]:
         """Get the props for the component.
@@ -1368,6 +1391,16 @@ class CustomComponent(Component):
             custom_components |= self.get_component(self).get_custom_components(
                 seen=seen
             )
+
+        # Fetch custom components from props as well.
+        for child_component in self.component_props.values():
+            if child_component.tag is None:
+                continue
+            if child_component.tag not in seen:
+                seen.add(child_component.tag)
+                if isinstance(child_component, CustomComponent):
+                    custom_components |= {child_component}
+                custom_components |= child_component.get_custom_components(seen=seen)
         return custom_components
 
     def _render(self) -> Tag: