Skip to content

yield rx.toast.info() doesn't get displayed on the UI when it's expected #6160

@LuizSuzana

Description

@LuizSuzana

Describe the bug
Inside a state class method (an event handler), I try to send some rx.toast components to the UI through yield rx.toast. However, they don't get displayed on the screen when they're expected to be, but instead, they get displayed altogether only when the method finishes its execution.

To Reproduce
On a blank new project, here's my app main script:

import asyncio
from collections.abc import AsyncGenerator
import reflex as rx

class State(rx.State):
    loading_data: bool = False
    building_plot: bool = False

    @rx.event
    async def handle_on_load(self) -> AsyncGenerator[rx.Component | None, None, None]:
        print(f"Page {self.router.url.path} loaded.")
        
        # load data
        self.loading_data = True
        yield
        await asyncio.sleep(3)  # loading data...
        self.loading_data = False
        yield
        
        yield rx.toast.info("Data loaded, starting plots", duration=10_000, close_button=True)
        
        # build plot
        self.building_plot = True
        yield
        await asyncio.sleep(3)  # building plot...
        self.building_plot = False
        yield
        yield rx.toast.info("Finished updating plots", duration=10_000, close_button=True)

def index() -> rx.Component:
    return rx.container(
        rx.vstack(
            rx.heading("Welcome to Reflex!", size="9"),
            rx.text(f"Loading data: {State.loading_data}"),
            rx.text(f"Building plot: {State.building_plot}"),
            spacing="5",
            justify="center",
            min_height="85vh",
        ),
    )

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

Expected behavior
On the screen, there are two text components to display the current value of the boolean attributes loading_data and building_plot; both are initialized with False. When the page is loaded or refreshed, State.handle_on_load is called and loading_data is set to True; after 3s, it switches to False and simultaneously building_plot becomes True; by this time (i.e. 3s after loading/refreshing the page), I expected a toast to be displayed on the screen, and it doesn't happen. By the end of the method execution (i.e. 6s after loading/refreshing the page), building_plot is set to False again, and the two toasts are finally displayed on the screen altogether.

To summarize, the unexpected behavior concerns the toast components, which seem to be held till the end of the method execution to finally be displayed on the screen. The boolean attributes loading_data and building_plot correctly switch between True/False, though.

Screenshots
Image

Specifics (please complete the following information):

  • Python Version: 3.11.14
  • Reflex Version: bug with both 0.8.26 and 0.8.27
  • OS: Manjaro (Linux)
  • Browser (Optional): Brave

Edit 1

Apparently, splitting the handle_on_load method into multiple events fixes the issue, although I would still expect the previous version to work correctly. Here's the on_load handler splitted:

    @rx.event
    async def handle_on_load_refactored(self):
        self.loading_data = True
        return State.load_data

    @rx.event
    async def load_data(self):
        await asyncio.sleep(5)
        self.loading_data = False
        yield rx.toast.info("Data loaded!")
        yield State.build_plot

    @rx.event
    async def build_plot(self):
        self.building_plot = True
        yield
        await asyncio.sleep(5)
        self.building_plot = False
        yield rx.toast.info("Plot built!")

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions