-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
State class variable is not shareing across pages and tabs #1857
Comments
In reflex, each tab gets its own state. So it's "expected" that opening the app in two different tabs will result in each tab storing However, within a single tab when I navigate between page1 and page2, I do see that the state is consistent; going to page1 and clicking the button makes it There is not a trivial way to link 2 states together... however you may consider the use of Changing the There is not currently a simple mechanism in reflex to keep the state of two or more tabs in sync live, because the reflex backend doesn't really know that any two states belong to the same user. If this is something that you want, then you can
I should stress that this is kind of a hack, but it does at least use public APIs. Here is a bit of sample code to help if you want to go down this road: import reflex as rx
# Keep track of tokens associated with the same client browser ("shared" sessions)
shared_sessions_by_token: dict[str, set[str]] = {}
# Keep track of (shared_token, state_token) pairs for each websocket connection (sid)
tokens_by_sid: dict[str, tuple[str, str]] = {}
class State(rx.State):
# The clientToken is saved in the browser and identifies "shared" sessions
clientToken: str = rx.Cookie("")
# The colorState is a special variable that is shared among all sessions with the same clientToken
colorState: str = "green"
def ChangePage1Color(self):
self.colorState = "red"
# Apply changes to all other shared sessions
return State.set_color_state_for_shared_sessions
def ChangePage2Color(self):
self.colorState = "yellow"
# Apply changes to all other shared sessions
return State.set_color_state_for_shared_sessions
async def set_color_state_for_shared_sessions(self):
"""Iterate through all shared sessions and update them with the new colorState."""
if not self.clientToken:
self.set_client_token()
print(f"{self.clientToken} -> {shared_sessions_by_token[self.clientToken]}")
for token in shared_sessions_by_token.get(self.clientToken, set()):
if token != self.get_token():
async with app.modify_state(token) as other_state:
other_state.colorState = self.colorState
async def set_color_state_for_new_session(self):
"""When a new session is created, copy the colorState from another shared session."""
for token in shared_sessions_by_token.get(self.clientToken, set()):
if token != self.get_token():
async with app.modify_state(token) as other_state:
self.colorState = other_state.colorState
return
def set_client_token(self):
"""Page on_load handler uses the clientToken cookie to identify shared sessions."""
if not self.clientToken:
self.clientToken = self.get_token()
# Mark this state's token as belonging to the clientToken
shared_sessions_by_token.setdefault(self.clientToken, set()).add(self.get_token())
# Mark this state's websocket id as belonging to the clientToken and state token
tokens_by_sid[self.get_sid()] = (self.clientToken, self.get_token())
# Set the colorState for the new session from existing shared sessions (if any)
return State.set_color_state_for_new_session
def page1() -> rx.Component:
return rx.vstack(
rx.button(
"Click 1",
on_click=State.ChangePage1Color,
),
rx.text(
State.colorState
)
)
def page2() -> rx.Component:
return rx.vstack(
rx.button(
"Click 2",
on_click=State.ChangePage2Color,
),
rx.text(
State.colorState
),
)
app = rx.App()
app.add_page(page1, on_load=State.set_client_token)
app.add_page(page2, on_load=State.set_client_token)
app.compile()
# Handle websocket disconnect events to avoid memory leaks when sessions are closed
orig_disconnect = app.event_namespace.on_disconnect
def disconnect_handler(sid):
orig_disconnect(sid)
clientToken, token = tokens_by_sid.get(sid, (None, None))
print(f"Disconnect event received for {sid}. Removing {token} from shared {clientToken}")
shared_sessions_by_token.get(clientToken, set()).discard(token)
tokens_by_sid.pop(sid, None)
app.event_namespace.on_disconnect = disconnect_handler Screen.Recording.2023-09-23.at.11.19.00.PM.mov |
Describe the bug
The state variable is not shared between the pages.
To Reproduce
The string variable is declared as a string in the state class.
code attached here as a python file code.txt
Expected behavior
Screenshots
Specifics (please complete the following information):
Additional context
Your effort on this library is literally awesome. I'm a big fan of your Reflex library.
but Your examples in the main documentation of the Reflex web page are not sufficient. If you provide more examples with different use cases for each component would be greatly helpful.
code.txt
The text was updated successfully, but these errors were encountered: