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

rx._x.client_state: react useState Var integration for frontend and backend #3269

Merged
merged 2 commits into from
May 16, 2024

Conversation

masenf
Copy link
Collaborator

@masenf masenf commented May 9, 2024

New experimental feature to create client-side react state vars, save them in the global refs object and access them in frontend rendering/event triggers as well on the backend via call_script.

A key difference in this implementation is the use of refs to avoid having to memoize components together in the same react function and to allow easy access to the browser state from the backend. This avoids some of the weirdness encountered with prior art: #2917 (comment)

Sample Code

import random

import reflex as rx


ClientSliderState = rx._x.client_state("slider_value", [0])


class State(rx.State):
    saved_value: list[int] = [50]

    def retrieve_callback(self, value: list[int]):
        self.saved_value = value
        return rx._x.toast.info(f"Saved value: {value[0]}")

    def save(self):
        return ClientSliderState.retrieve(
            callback=State.retrieve_callback,
        )

    def randomize(self):
        self.saved_value = [random.randint(0, 100)]
        return self.on_load()

    def on_load(self):
        return ClientSliderState.push(self.saved_value)


def index() -> rx.Component:
    return rx.container(
        ClientSliderState,  # Set up the client state in top-level component.
        rx.vstack(
            rx.heading("Welcome to Client Slider!", size="9"),
            rx.divider(margin_bottom="2em"),
            rx.hstack(
                rx.heading("Client Value: "),
                rx.spinner(
                    rx.heading(ClientSliderState.value[0]),
                    loading=~rx.State.is_hydrated,
                ),
                rx.spacer(),
                rx.heading("Server Value: "),
                rx.spinner(
                    rx.heading(State.saved_value[0]),
                    loading=~rx.State.is_hydrated,
                ),
            ),
            rx.slider(
                value=rx.cond(rx.State.is_hydrated, ClientSliderState.value, []),
                on_change=ClientSliderState.set,
            ),
            rx.hstack(
                rx.button("Save", on_click=State.save),
                rx.button("Randomize", on_click=State.randomize),
                justify="center",
            ),
            rx.logo(),
            rx._x.toast.provider(),
            spacing="5",
            align="center",
        ),
        padding_top="3em",
        height="100vh",
        stack_children_full_width=True,
    )


app = rx.App()
app.add_page(index, on_load=State.on_load)

…ackend

New experimental feature to create client-side react state vars, save them in
the global `refs` object and access them in frontend rendering/event triggers
as well on the backend via call_script.
Lendemor
Lendemor previously approved these changes May 15, 2024
@masenf masenf merged commit 89352ac into main May 16, 2024
47 checks passed
@masenf masenf deleted the masenf/local-state-experiment branch May 16, 2024 20:20
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.

None yet

2 participants