Kaynağa Gözat

Generalize MemoizationLeaf Component mixin (#2247)

Masen Furer 1 yıl önce
ebeveyn
işleme
49ccd2f1fb

+ 2 - 2
reflex/components/base/head.py

@@ -1,6 +1,6 @@
 """The head component."""
 
-from reflex.components.component import Component
+from reflex.components.component import Component, MemoizationLeaf
 
 
 class NextHeadLib(Component):
@@ -9,7 +9,7 @@ class NextHeadLib(Component):
     library = "next/head"
 
 
-class Head(NextHeadLib):
+class Head(NextHeadLib, MemoizationLeaf):
     """Head Component."""
 
     tag = "NextHead"

+ 4 - 7
reflex/components/base/head.pyi

@@ -7,7 +7,7 @@ from typing import Any, Dict, Literal, Optional, Union, overload
 from reflex.vars import Var, BaseVar, ComputedVar
 from reflex.event import EventChain, EventHandler, EventSpec
 from reflex.style import Style
-from reflex.components.component import Component
+from reflex.components.component import Component, MemoizationLeaf
 
 class NextHeadLib(Component):
     @overload
@@ -88,7 +88,7 @@ class NextHeadLib(Component):
         """
         ...
 
-class Head(NextHeadLib):
+class Head(NextHeadLib, MemoizationLeaf):
     @overload
     @classmethod
     def create(  # type: ignore
@@ -147,7 +147,7 @@ class Head(NextHeadLib):
         ] = None,
         **props
     ) -> "Head":
-        """Create the component.
+        """Create a new memoization leaf component.
 
         Args:
             *children: The children of the component.
@@ -160,9 +160,6 @@ class Head(NextHeadLib):
             **props: The props of the component.
 
         Returns:
-            The component.
-
-        Raises:
-            TypeError: If an invalid child is passed.
+            The memoization leaf
         """
         ...

+ 32 - 0
reflex/components/component.py

@@ -1674,3 +1674,35 @@ class StatefulComponent(BaseComponent):
             if stateful_component is not None:
                 return stateful_component
         return component
+
+
+class MemoizationLeaf(Component):
+    """A component that does not separately memoize its children.
+
+    Any component which depends on finding the exact names of children
+    components within it, should be a memoization leaf so the compiler
+    does not replace the provided child tags with memoized tags.
+
+    During creation, a memoization leaf will mark itself as wanting to be
+    memoized if any of its children return any hooks.
+    """
+
+    _memoization_mode = MemoizationMode(recursive=False)
+
+    @classmethod
+    def create(cls, *children, **props) -> Component:
+        """Create a new memoization leaf component.
+
+        Args:
+            *children: The children of the component.
+            **props: The props of the component.
+
+        Returns:
+            The memoization leaf
+        """
+        comp = super().create(*children, **props)
+        if comp.get_hooks():
+            comp._memoization_mode = cls._memoization_mode.copy(
+                update={"disposition": MemoizationDisposition.ALWAYS}
+            )
+        return comp

+ 3 - 3
reflex/components/graphing/recharts/charts.pyi

@@ -770,10 +770,10 @@ class FunnelChart(RechartsCharts):
         ] = None,
         **props
     ) -> "FunnelChart":
-        """Create a Recharts chart container component (mixin).
+        """Create a new memoization leaf component.
 
         Args:
-            *children: The children components.
+            *children: The children of the component.
             data: The source data, in which each element is an object.
             sync_id: If any two categorical charts(rx.line_chart, rx.area_chart, rx.bar_chart, rx.composed_chart) have the same sync_id, these two charts can sync the position GraphingTooltip, and the start_index, end_index of Brush.
             sync_method: When sync_id is provided, allows customisation of how the charts will synchronize GraphingTooltips and brushes. Using 'index' (default setting), other charts will reuse current datum's index within the data array. In cases where data does not have the same length, this might yield unexpected results. In that case use 'value' which will try to match other charts values, or a fully custom function which will receive tick, data as argument and should return an index. 'index' | 'value' | function
@@ -791,7 +791,7 @@ class FunnelChart(RechartsCharts):
             **props: The props of the component.
 
         Returns:
-            A Recharts component.
+            The memoization leaf
         """
         ...
 

+ 2 - 2
reflex/components/graphing/recharts/general.py

@@ -3,6 +3,7 @@ from __future__ import annotations
 
 from typing import Any, Dict, List, Union
 
+from reflex.components.component import MemoizationLeaf
 from reflex.constants import EventTriggers
 from reflex.vars import Var
 
@@ -13,11 +14,10 @@ from .recharts import (
     LiteralPosition,
     LiteralVerticalAlign,
     Recharts,
-    RechartsMemoizationLeafMixin,
 )
 
 
-class ResponsiveContainer(Recharts, RechartsMemoizationLeafMixin):
+class ResponsiveContainer(Recharts, MemoizationLeaf):
     """A base class for responsive containers in Recharts."""
 
     tag = "ResponsiveContainer"

+ 5 - 5
reflex/components/graphing/recharts/general.pyi

@@ -8,6 +8,7 @@ from reflex.vars import Var, BaseVar, ComputedVar
 from reflex.event import EventChain, EventHandler, EventSpec
 from reflex.style import Style
 from typing import Any, Dict, List, Union
+from reflex.components.component import MemoizationLeaf
 from reflex.constants import EventTriggers
 from reflex.vars import Var
 from .recharts import (
@@ -17,10 +18,9 @@ from .recharts import (
     LiteralPosition,
     LiteralVerticalAlign,
     Recharts,
-    RechartsMemoizationLeafMixin,
 )
 
-class ResponsiveContainer(Recharts, RechartsMemoizationLeafMixin):
+class ResponsiveContainer(Recharts, MemoizationLeaf):
     @overload
     @classmethod
     def create(  # type: ignore
@@ -85,10 +85,10 @@ class ResponsiveContainer(Recharts, RechartsMemoizationLeafMixin):
         ] = None,
         **props
     ) -> "ResponsiveContainer":
-        """Create a Recharts chart container component (mixin).
+        """Create a new memoization leaf component.
 
         Args:
-            *children: The children components.
+            *children: The children of the component.
             aspect: The aspect ratio of the container. The final aspect ratio of the SVG element will be (width / height) * aspect. Number
             width: The width of chart container. Can be a number or string
             height: The height of chart container. Number
@@ -104,7 +104,7 @@ class ResponsiveContainer(Recharts, RechartsMemoizationLeafMixin):
             **props: The props of the component.
 
         Returns:
-            A Recharts component.
+            The memoization leaf
         """
         ...
 

+ 2 - 31
reflex/components/graphing/recharts/recharts.py

@@ -1,8 +1,7 @@
 """A component that wraps a recharts lib."""
 from typing import Literal
 
-from reflex.components.component import Component, NoSSRComponent
-from reflex.constants import MemoizationDisposition, MemoizationMode
+from reflex.components.component import Component, MemoizationLeaf, NoSSRComponent
 
 
 class Recharts(Component):
@@ -11,35 +10,7 @@ class Recharts(Component):
     library = "recharts@2.8.0"
 
 
-class RechartsMemoizationLeafMixin(Component):
-    """A mixin for Recharts components that must not memoize their children separately.
-
-    This includes all chart types and ResponsiveContainer itself.
-    """
-
-    _memoization_mode = MemoizationMode(recursive=False)
-
-    @classmethod
-    def create(cls, *children, **props) -> Component:
-        """Create a Recharts chart container component (mixin).
-
-        Args:
-            *children: The children components.
-            **props: The props of the component.
-
-        Returns:
-            A Recharts component.
-        """
-        comp = super().create(*children, **props)
-        if comp.get_hooks():
-            # If any of the children depend on state, then this instance needs to memoize.
-            comp._memoization_mode = cls._memoization_mode.copy(
-                update={"disposition": MemoizationDisposition.ALWAYS},
-            )
-        return comp
-
-
-class RechartsCharts(NoSSRComponent, RechartsMemoizationLeafMixin):
+class RechartsCharts(NoSSRComponent, MemoizationLeaf):
     """A component that wraps a recharts lib."""
 
     library = "recharts@2.8.0"

+ 5 - 82
reflex/components/graphing/recharts/recharts.pyi

@@ -8,8 +8,7 @@ from reflex.vars import Var, BaseVar, ComputedVar
 from reflex.event import EventChain, EventHandler, EventSpec
 from reflex.style import Style
 from typing import Literal
-from reflex.components.component import Component, NoSSRComponent
-from reflex.constants import MemoizationDisposition, MemoizationMode
+from reflex.components.component import Component, MemoizationLeaf, NoSSRComponent
 
 class Recharts(Component):
     @overload
@@ -90,83 +89,7 @@ class Recharts(Component):
         """
         ...
 
-class RechartsMemoizationLeafMixin(Component):
-    @overload
-    @classmethod
-    def create(  # type: ignore
-        cls,
-        *children,
-        style: Optional[Style] = None,
-        key: Optional[Any] = None,
-        id: Optional[Any] = None,
-        class_name: Optional[Any] = None,
-        autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
-        on_blur: Optional[
-            Union[EventHandler, EventSpec, list, function, BaseVar]
-        ] = None,
-        on_click: Optional[
-            Union[EventHandler, EventSpec, list, function, BaseVar]
-        ] = None,
-        on_context_menu: Optional[
-            Union[EventHandler, EventSpec, list, function, BaseVar]
-        ] = None,
-        on_double_click: Optional[
-            Union[EventHandler, EventSpec, list, function, BaseVar]
-        ] = None,
-        on_focus: Optional[
-            Union[EventHandler, EventSpec, list, function, BaseVar]
-        ] = None,
-        on_mount: Optional[
-            Union[EventHandler, EventSpec, list, function, BaseVar]
-        ] = None,
-        on_mouse_down: Optional[
-            Union[EventHandler, EventSpec, list, function, BaseVar]
-        ] = None,
-        on_mouse_enter: Optional[
-            Union[EventHandler, EventSpec, list, function, BaseVar]
-        ] = None,
-        on_mouse_leave: Optional[
-            Union[EventHandler, EventSpec, list, function, BaseVar]
-        ] = None,
-        on_mouse_move: Optional[
-            Union[EventHandler, EventSpec, list, function, BaseVar]
-        ] = None,
-        on_mouse_out: Optional[
-            Union[EventHandler, EventSpec, list, function, BaseVar]
-        ] = None,
-        on_mouse_over: Optional[
-            Union[EventHandler, EventSpec, list, function, BaseVar]
-        ] = None,
-        on_mouse_up: Optional[
-            Union[EventHandler, EventSpec, list, function, BaseVar]
-        ] = None,
-        on_scroll: Optional[
-            Union[EventHandler, EventSpec, list, function, BaseVar]
-        ] = None,
-        on_unmount: Optional[
-            Union[EventHandler, EventSpec, list, function, BaseVar]
-        ] = None,
-        **props
-    ) -> "RechartsMemoizationLeafMixin":
-        """Create a Recharts chart container component (mixin).
-
-        Args:
-            *children: The children components.
-            style: The style of the component.
-            key: A unique key for the component.
-            id: The id for the component.
-            class_name: The class name for the component.
-            autofocus: Whether the component should take the focus once the page is loaded
-            custom_attrs: custom attribute
-            **props: The props of the component.
-
-        Returns:
-            A Recharts component.
-        """
-        ...
-
-class RechartsCharts(NoSSRComponent, RechartsMemoizationLeafMixin):
+class RechartsCharts(NoSSRComponent, MemoizationLeaf):
     @overload
     @classmethod
     def create(  # type: ignore
@@ -225,10 +148,10 @@ class RechartsCharts(NoSSRComponent, RechartsMemoizationLeafMixin):
         ] = None,
         **props
     ) -> "RechartsCharts":
-        """Create a Recharts chart container component (mixin).
+        """Create a new memoization leaf component.
 
         Args:
-            *children: The children components.
+            *children: The children of the component.
             style: The style of the component.
             key: A unique key for the component.
             id: The id for the component.
@@ -238,7 +161,7 @@ class RechartsCharts(NoSSRComponent, RechartsMemoizationLeafMixin):
             **props: The props of the component.
 
         Returns:
-            A Recharts component.
+            The memoization leaf
         """
         ...
 

+ 2 - 2
reflex/components/layout/cond.py

@@ -3,7 +3,7 @@ from __future__ import annotations
 
 from typing import Any, Dict, Optional, overload
 
-from reflex.components.component import BaseComponent, Component
+from reflex.components.component import BaseComponent, Component, MemoizationLeaf
 from reflex.components.layout.fragment import Fragment
 from reflex.components.tags import CondTag, Tag
 from reflex.constants import Dirs
@@ -15,7 +15,7 @@ _IS_TRUE_IMPORT = {
 }
 
 
-class Cond(Component):
+class Cond(MemoizationLeaf):
     """Render one of two components based on a condition."""
 
     # The cond to determine which component to render.