Skip to content
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

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

Merged
merged 4 commits into from
Nov 5, 2024

Conversation

Lendemor
Copy link
Collaborator

@Lendemor Lendemor commented Sep 19, 2024

small example sending state info related to a specific token through API

import reflex as rx
from fastapi import Request, Response

class State(rx.State):
    foo = "bar"

@rx.page()
def index():
    return rx.text(State.router.session.client_token)

app = rx.App()

@app.api.route("/api")
async def get(request: Request):
    token = "add_token_here" # copy the one rendered in the page
    state = await rx.get_state(token, State)
    return Response(state.foo)

Copy link
Collaborator

@masenf masenf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a bit of a dangerous API, because if the state is modified, then that is essentially thrown away (unless in dev mode).

i think it would be better to expose a wrapper over app.modify_state with an async contextmanager.

if we definitely want a get_state that maybe skips taking a lock or sending an update or something, i think that's okay, but we should wrap it in a StateProxy like a background task so it cannot be modified outside of async with state:

@Lendemor
Copy link
Collaborator Author

Lendemor commented Sep 20, 2024

this is a bit of a dangerous API, because if the state is modified, then that is essentially thrown away (unless in dev mode).

i think it would be better to expose a wrapper over app.modify_state with an async contextmanager.

if we definitely want a get_state that maybe skips taking a lock or sending an update or something, i think that's okay, but we should wrap it in a StateProxy like a background task so it cannot be modified outside of async with state:

I think it could have its use, mostly as a way to get a snapshot of the state at instant t (when the API request arrive for example)

it's a part of this POC: #2819, stripped down for minimal changes.

I do plan to also wrap / expose modify_state, but it'll be more complex because we need to solve the synchronicity problem between workers (above PR has a solution, but if redis is optional, I'm not sure it's applicable anymore)

rx.get_state should follow the same rules as State.get_state ie => read-only

@masenf
Copy link
Collaborator

masenf commented Sep 20, 2024

rx.get_state should follow the same rules as State.get_state ie => read-only

When you do await self.get_state(MyState) inside an event handler, you can modify the state that comes back, it's not read-only

@Lendemor
Copy link
Collaborator Author

I see.

Will have to brainstorm a bit on this to figure out the ideal way.

@Lendemor Lendemor merged commit 0ed7c5d into main Nov 5, 2024
31 checks passed
@masenf masenf deleted the lendemor/expose_get_state_at_top_level branch December 12, 2024 07:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants