diff --git a/reflex/__init__.py b/reflex/__init__.py index 74e4832ee..611d2765a 100644 --- a/reflex/__init__.py +++ b/reflex/__init__.py @@ -112,6 +112,7 @@ _ALL_COMPONENTS = [ ] _MAPPING = { + "reflex.experimental": ["_x"], "reflex.admin": ["admin", "AdminDash"], "reflex.app": ["app", "App", "UploadFile"], "reflex.base": ["base", "Base"], diff --git a/reflex/__init__.pyi b/reflex/__init__.pyi index 5b46dd4f4..4af037bd1 100644 --- a/reflex/__init__.pyi +++ b/reflex/__init__.pyi @@ -1,3 +1,4 @@ +from reflex.experimental import _x as _x from reflex import admin as admin from reflex.admin import AdminDash as AdminDash from reflex import app as app diff --git a/reflex/experimental/__init__.py b/reflex/experimental/__init__.py new file mode 100644 index 000000000..5c5fae9a7 --- /dev/null +++ b/reflex/experimental/__init__.py @@ -0,0 +1,14 @@ +"""Namespace for experimental features.""" + +from types import SimpleNamespace + +from ..utils.console import warn +from . import hooks as hooks + +warn( + "`rx._x` contains experimental features and might be removed at any time in the future .", +) + +_x = SimpleNamespace( + hooks=hooks, +) diff --git a/reflex/experimental/hooks.py b/reflex/experimental/hooks.py new file mode 100644 index 000000000..ba430296a --- /dev/null +++ b/reflex/experimental/hooks.py @@ -0,0 +1,75 @@ +"""Add standard Hooks wrapper for React.""" + +from reflex.utils.imports import ImportVar +from reflex.vars import Var, VarData + + +def _add_react_import(v: Var | None, tags: str | list): + if v is None: + return + + if isinstance(tags, str): + tags = [tags] + + v._var_data = VarData( # type: ignore + imports={"react": [ImportVar(tag=tag) for tag in tags]}, + ) + + +def const(name, value) -> Var | None: + """Create a constant Var. + + Args: + name: The name of the constant. + value: The value of the constant. + + Returns: + The constant Var. + """ + return Var.create(f"const {name} = {value}") + + +def useCallback(func, deps) -> Var | None: + """Create a useCallback hook with a function and dependencies. + + Args: + func: The function to wrap. + deps: The dependencies of the function. + + Returns: + The useCallback hook. + """ + if deps: + v = Var.create(f"useCallback({func}, {deps})") + else: + v = Var.create(f"useCallback({func})") + _add_react_import(v, "useCallback") + return v + + +def useContext(context) -> Var | None: + """Create a useContext hook with a context. + + Args: + context: The context to use. + + Returns: + The useContext hook. + """ + v = Var.create(f"useContext({context})") + _add_react_import(v, "useContext") + return v + + +def useRef(default) -> Var | None: + """Create a useRef hook with a default value. + + Args: + default: The default value of the ref. + + Returns: + The useRef hook. + """ + v = Var.create(f"useRef({default})") + _add_react_import(v, "useRef") + return v