expose rx.get_state() to get instance of state from anywhere (#3959)

* expose rx.get_state() to get instance of state from anywhere

* fix circular import and add read-only proxy
This commit is contained in:
Thomas Brandého 2024-11-05 07:21:59 -08:00 committed by GitHub
parent bb903b605a
commit 0ed7c5d969
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 67 additions and 0 deletions

View File

@ -336,6 +336,7 @@ _MAPPING: dict = {
"State", "State",
"dynamic", "dynamic",
], ],
"istate.wrappers": ["get_state"],
"style": ["Style", "toggle_color_mode"], "style": ["Style", "toggle_color_mode"],
"utils.imports": ["ImportVar"], "utils.imports": ["ImportVar"],
"utils.serializers": ["serializer"], "utils.serializers": ["serializer"],

View File

@ -180,6 +180,7 @@ from .experimental import _x as _x
from .istate.storage import Cookie as Cookie from .istate.storage import Cookie as Cookie
from .istate.storage import LocalStorage as LocalStorage from .istate.storage import LocalStorage as LocalStorage
from .istate.storage import SessionStorage as SessionStorage from .istate.storage import SessionStorage as SessionStorage
from .istate.wrappers import get_state as get_state
from .middleware import Middleware as Middleware from .middleware import Middleware as Middleware
from .middleware import middleware as middleware from .middleware import middleware as middleware
from .model import Model as Model from .model import Model as Model

View File

@ -0,0 +1 @@
"""This module will provide interfaces for the state."""

33
reflex/istate/proxy.py Normal file
View File

@ -0,0 +1,33 @@
"""A module to hold state proxy classes."""
from typing import Any
from reflex.state import StateProxy
class ReadOnlyStateProxy(StateProxy):
"""A read-only proxy for a state."""
def __setattr__(self, name: str, value: Any) -> None:
"""Prevent setting attributes on the state for read-only proxy.
Args:
name: The attribute name.
value: The attribute value.
Raises:
NotImplementedError: Always raised when trying to set an attribute on proxied state.
"""
if name.startswith("_self_"):
# Special case attributes of the proxy itself, not applied to the wrapped object.
super().__setattr__(name, value)
return
raise NotImplementedError("This is a read-only state proxy.")
def mark_dirty(self):
"""Mark the state as dirty.
Raises:
NotImplementedError: Always raised when trying to mark the proxied state as dirty.
"""
raise NotImplementedError("This is a read-only state proxy.")

31
reflex/istate/wrappers.py Normal file
View File

@ -0,0 +1,31 @@
"""Wrappers for the state manager."""
from typing import Any
from reflex.istate.proxy import ReadOnlyStateProxy
from reflex.state import (
_split_substate_key,
_substate_key,
get_state_manager,
)
async def get_state(token, state_cls: Any | None = None) -> ReadOnlyStateProxy:
"""Get the instance of a state for a token.
Args:
token: The token for the state.
state_cls: The class of the state.
Returns:
A read-only proxy of the state instance.
"""
mng = get_state_manager()
if state_cls is not None:
root_state = await mng.get_state(_substate_key(token, state_cls))
else:
root_state = await mng.get_state(token)
_, state_path = _split_substate_key(token)
state_cls = root_state.get_class_substate(tuple(state_path.split(".")))
instance = await root_state.get_state(state_cls)
return ReadOnlyStateProxy(instance)