Generalize MemoizationLeaf Component mixin (#2247)

This commit is contained in:
Masen Furer 2023-12-01 11:41:11 -08:00 committed by GitHub
parent 1109f8f508
commit 49ccd2f1fb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 57 additions and 134 deletions

View File

@ -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"

View File

@ -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
"""
...

View File

@ -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

View File

@ -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
"""
...

View File

@ -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"

View File

@ -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
"""
...

View File

@ -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"

View File

@ -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
"""
...

View File

@ -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.