Problem with the loading property of a button

I have an issue I can’t resolve with the loading property of a button within a custom login form. I’m using a fork of the excellent repository GitHub - masenf/reflex-local-auth to make it compatible with the database I use, which is Azure SQL Server.

For the login form, I’m using the recipe included in the Reflex documentation, specifically the one called “Icons” (Login Form).

To handle the submit, I encapsulate it in a form like this:

def login_card() -> rx.Component:
    return rx.form(
        rx.card(
            rx.vstack(
                rx.center(
                    rx.image(
                        src="/logo.png",
                        ...
                    )
                ),
                ...
            ),
            # on_submit=LoginState.on_submit,
            on_submit=State.handle_login_submit,  # I encapsulate the reflex_local_auth on_submit function in this handle_login_submit function to manage the boolean state of is_loading_login
        )
    )

Notice that I’m not directly calling on_submit from reflex-local-auth; instead, I’ll do this through another function to avoid modifying the included repository code, making future maintenance easier.

The code for that function is:

@rx.event
def handle_login_submit(self, form_data: dict):
    self.is_loading_login = True
    yield 
    try:
        login_result = LoginState.on_submit(form_data)
        yield login_result
    finally:
        self.is_loading_login = False
        yield

This function is in my state.py .

I’m not sure what I’m doing wrong, but yield isn’t working as expected. The login page doesn’t refresh, and the button doesn’t show its loading state.

The issue is related to the way you’re using yield within the event handler. Reflex’s event system expects components to react to state changes and triggers re-rendering based on those changes.

@rx.event
def handle_login_submit(self, form_data: dict):
    self.is_loading_login = True
    try:
        login_result = LoginState.on_submit(form_data)
        self.is_loading_login = False
        return login_result
    except Exception as e:
        self.is_loading_login = False
        raise e

Thanks for the feedback and the help.

I replaced my function with yours, but the behavior is still the same. Any ideas on how I can fix or debug it?

Unless you set @rx.event(background=True) then I don’t think the self.is_loading_login = True will have any effect since you’re changing it back to false before returning from the handler, and the state update only triggers at that point.

Not sure if that addresses the issue you are facing, but something to be aware of.

I don’t think you can easily wait for the result of a different event handler from within one event. You can only trigger others to start via yield/return event handler methods, but those won’t necessarily finish before your method continues on.

If you want to change other states within a single callback, you can use other_state_inst = await self.get_state(OtherState) and make modifications to it from the instance you get back. Does that help you?

late reply, but give this a shot

@rx.event
async def handle_login_submit(self, form_data: dict):
    self.is_loading_login = True
    yield 
    try:
        login_state = await self.get_state(LoginState)
        return login_state.on_submit(form_data)
    finally:
        self.is_loading_login = False