implement rx dynamic (#4195)
* implement rx dynamic * dang it darglint * add custom type
This commit is contained in:
parent
a65fc2e90b
commit
3eab2b6e7d
@ -331,6 +331,7 @@ _MAPPING: dict = {
|
||||
"var",
|
||||
"ComponentState",
|
||||
"State",
|
||||
"dynamic",
|
||||
],
|
||||
"style": ["Style", "toggle_color_mode"],
|
||||
"utils.imports": ["ImportVar"],
|
||||
|
@ -184,6 +184,7 @@ from .model import session as session
|
||||
from .page import page as page
|
||||
from .state import ComponentState as ComponentState
|
||||
from .state import State as State
|
||||
from .state import dynamic as dynamic
|
||||
from .state import var as var
|
||||
from .style import Style as Style
|
||||
from .style import toggle_color_mode as toggle_color_mode
|
||||
|
@ -30,6 +30,7 @@ from typing import (
|
||||
Set,
|
||||
Tuple,
|
||||
Type,
|
||||
TypeVar,
|
||||
Union,
|
||||
cast,
|
||||
get_args,
|
||||
@ -79,6 +80,7 @@ from reflex.utils import console, format, path_ops, prerequisites, types
|
||||
from reflex.utils.exceptions import (
|
||||
ComputedVarShadowsBaseVars,
|
||||
ComputedVarShadowsStateVar,
|
||||
DynamicComponentInvalidSignature,
|
||||
DynamicRouteArgShadowsStateVar,
|
||||
EventHandlerShadowsBuiltInStateMethod,
|
||||
ImmutableStateError,
|
||||
@ -2095,6 +2097,51 @@ class State(BaseState):
|
||||
is_hydrated: bool = False
|
||||
|
||||
|
||||
T = TypeVar("T", bound=BaseState)
|
||||
|
||||
|
||||
def dynamic(func: Callable[[T], Component]):
|
||||
"""Create a dynamically generated components from a state class.
|
||||
|
||||
Args:
|
||||
func: The function to generate the component.
|
||||
|
||||
Returns:
|
||||
The dynamically generated component.
|
||||
|
||||
Raises:
|
||||
DynamicComponentInvalidSignature: If the function does not have exactly one parameter.
|
||||
DynamicComponentInvalidSignature: If the function does not have a type hint for the state class.
|
||||
"""
|
||||
number_of_parameters = len(inspect.signature(func).parameters)
|
||||
|
||||
func_signature = get_type_hints(func)
|
||||
|
||||
if "return" in func_signature:
|
||||
func_signature.pop("return")
|
||||
|
||||
values = list(func_signature.values())
|
||||
|
||||
if number_of_parameters != 1:
|
||||
raise DynamicComponentInvalidSignature(
|
||||
"The function must have exactly one parameter, which is the state class."
|
||||
)
|
||||
|
||||
if len(values) != 1:
|
||||
raise DynamicComponentInvalidSignature(
|
||||
"You must provide a type hint for the state class in the function."
|
||||
)
|
||||
|
||||
state_class: Type[T] = values[0]
|
||||
|
||||
def wrapper() -> Component:
|
||||
from reflex.components.base.fragment import fragment
|
||||
|
||||
return fragment(state_class._evaluate(lambda state: func(state)))
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
class FrontendEventExceptionState(State):
|
||||
"""Substate for handling frontend exceptions."""
|
||||
|
||||
|
@ -139,3 +139,7 @@ class StateSchemaMismatchError(ReflexError, TypeError):
|
||||
|
||||
class EnvironmentVarValueError(ReflexError, ValueError):
|
||||
"""Raised when an environment variable is set to an invalid value."""
|
||||
|
||||
|
||||
class DynamicComponentInvalidSignature(ReflexError, TypeError):
|
||||
"""Raised when a dynamic component has an invalid signature."""
|
||||
|
Loading…
Reference in New Issue
Block a user