소스 검색

implement rx dynamic (#4195)

* implement rx dynamic

* dang it darglint

* add custom type
Khaleel Al-Adhami 6 달 전
부모
커밋
3eab2b6e7d
4개의 변경된 파일53개의 추가작업 그리고 0개의 파일을 삭제
  1. 1 0
      reflex/__init__.py
  2. 1 0
      reflex/__init__.pyi
  3. 47 0
      reflex/state.py
  4. 4 0
      reflex/utils/exceptions.py

+ 1 - 0
reflex/__init__.py

@@ -331,6 +331,7 @@ _MAPPING: dict = {
         "var",
         "var",
         "ComponentState",
         "ComponentState",
         "State",
         "State",
+        "dynamic",
     ],
     ],
     "style": ["Style", "toggle_color_mode"],
     "style": ["Style", "toggle_color_mode"],
     "utils.imports": ["ImportVar"],
     "utils.imports": ["ImportVar"],

+ 1 - 0
reflex/__init__.pyi

@@ -184,6 +184,7 @@ from .model import session as session
 from .page import page as page
 from .page import page as page
 from .state import ComponentState as ComponentState
 from .state import ComponentState as ComponentState
 from .state import State as State
 from .state import State as State
+from .state import dynamic as dynamic
 from .state import var as var
 from .state import var as var
 from .style import Style as Style
 from .style import Style as Style
 from .style import toggle_color_mode as toggle_color_mode
 from .style import toggle_color_mode as toggle_color_mode

+ 47 - 0
reflex/state.py

@@ -30,6 +30,7 @@ from typing import (
     Set,
     Set,
     Tuple,
     Tuple,
     Type,
     Type,
+    TypeVar,
     Union,
     Union,
     cast,
     cast,
     get_args,
     get_args,
@@ -79,6 +80,7 @@ from reflex.utils import console, format, path_ops, prerequisites, types
 from reflex.utils.exceptions import (
 from reflex.utils.exceptions import (
     ComputedVarShadowsBaseVars,
     ComputedVarShadowsBaseVars,
     ComputedVarShadowsStateVar,
     ComputedVarShadowsStateVar,
+    DynamicComponentInvalidSignature,
     DynamicRouteArgShadowsStateVar,
     DynamicRouteArgShadowsStateVar,
     EventHandlerShadowsBuiltInStateMethod,
     EventHandlerShadowsBuiltInStateMethod,
     ImmutableStateError,
     ImmutableStateError,
@@ -2095,6 +2097,51 @@ class State(BaseState):
     is_hydrated: bool = False
     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):
 class FrontendEventExceptionState(State):
     """Substate for handling frontend exceptions."""
     """Substate for handling frontend exceptions."""
 
 

+ 4 - 0
reflex/utils/exceptions.py

@@ -139,3 +139,7 @@ class StateSchemaMismatchError(ReflexError, TypeError):
 
 
 class EnvironmentVarValueError(ReflexError, ValueError):
 class EnvironmentVarValueError(ReflexError, ValueError):
     """Raised when an environment variable is set to an invalid value."""
     """Raised when an environment variable is set to an invalid value."""
+
+
+class DynamicComponentInvalidSignature(ReflexError, TypeError):
+    """Raised when a dynamic component has an invalid signature."""