Explorar o código

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 hai 1 ano
pai
achega
86a1e8a07e
Modificáronse 1 ficheiros con 33 adicións e 0 borrados
  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.
     # The props of the component.
     props: Dict[str, Any] = {}
     props: Dict[str, Any] = {}
 
 
+    # Props that reference other components.
+    component_props: Dict[str, Component] = {}
+
     def __init__(self, *args, **kwargs):
     def __init__(self, *args, **kwargs):
         """Initialize the custom component.
         """Initialize the custom component.
 
 
@@ -1302,6 +1305,7 @@ class CustomComponent(Component):
 
 
                 # Track hooks and imports associated with Component instances.
                 # Track hooks and imports associated with Component instances.
                 if base_value is not None and isinstance(value, Component):
                 if base_value is not None and isinstance(value, Component):
+                    self.component_props[key] = value
                     value = base_value._replace(
                     value = base_value._replace(
                         merge_var_data=VarData(  # type: ignore
                         merge_var_data=VarData(  # type: ignore
                             imports=value.get_imports(),
                             imports=value.get_imports(),
@@ -1335,6 +1339,25 @@ class CustomComponent(Component):
         """
         """
         return hash(self.tag)
         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
     @classmethod
     def get_props(cls) -> Set[str]:
     def get_props(cls) -> Set[str]:
         """Get the props for the component.
         """Get the props for the component.
@@ -1368,6 +1391,16 @@ class CustomComponent(Component):
             custom_components |= self.get_component(self).get_custom_components(
             custom_components |= self.get_component(self).get_custom_components(
                 seen=seen
                 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
         return custom_components
 
 
     def _render(self) -> Tag:
     def _render(self) -> Tag: