reflex icon indicating copy to clipboard operation
reflex copied to clipboard

on_mount calls a fn twice and on_load calls a fn tree times on debug mode.

Open iBuitron opened this issue 9 months ago β€’ 1 comments

Problem: https://discord.com/channels/1029853095527727165/1239586151178703020

when i use my AsyncClient to fech data on my API (on Debug Mode):

The INFO LOG at the API
on_load -> call/fetch tree times
on_mount -> call/fetch two times
When i use with a button, just call/fetch once.

This is my Async client: (i remove the async with cuz reflex said: client was close)

# -------------------------------------------------------------------
# QuickBio API Async client
# -------------------------------------------------------------------

async_client = httpx.AsyncClient(base_url=URL_BASE, timeout=None)



@dataclass
class QbAsyncClient:
    """Sync client for QuickBio API"""

    user_id: str | None = None
    endpoint: str | None = None
    client: httpx.AsyncClient = async_client

    async def get(self) -> Any:
        headers = {"user_id": self.user_id} if self.user_id else {}

        # async with self.client as client:
        response = await self.client.get(url=self.endpoint, headers=headers)
        print(response)
        # response = await self.client.get(url=self.endpoint, headers=headers)

        if response.status_code == 200:
            return response.json()

    async def post(self, data: str) -> Any:
        """Every data should be a model dump json"""

        headers = {"user_id": self.user_id} if self.user_id else {}

        # async with self.client as client:
        response = await self.client.post(url=self.endpoint, headers=headers, data=data)

        if response.status_code == 200:
            return response.json()

This is when i call

import reflex as rx

from ....api.client import QbAsyncClient


class MyTask(rx.State):
    bars: list[str]

    @rx.background
    async def get_bars(self):
        bars = await QbAsyncClient(
            endpoint="/analysis/richness/histogram/barmode"
        ).get()
        # The API returns a list ['group', 'stack']

        print(bars)
        async with self:
            self.bars = bars


def render() -> rx.Component:
    return rx.box(
        rx.vstack(
            # rx.button(
            #     "connect to client",
            #     on_click=MyTask.get_bars,
            # ),
            rx.select(
                MyTask.bars,
                on_mount=MyTask.get_bars,
                placeholder="Select a bar mode",
            ),
        )
    )

I fix this with a if statement

class MyTask(rx.State):
    bars: list[str] = []

    @rx.background
    async def get_bars(self):
        async with self:
            print(self.bars)

            if not self.bars:
                bars = await QbAsyncClient(
                    endpoint="/analysis/richness/histogram/barmode"
                ).get()

                self.bars = bars
On the INFO LOG at the API just call once 
But still print twice
with 'reflex run --env prod' call once  without the 'if not self.bars'

iBuitron avatar May 13 '24 15:05 iBuitron

Confirming that I have also ran into this problem. There also might be an issue with on_load. I basically had to pull all of the on_loads out of my code and change them to on_mount. Sometimes it would stop the new page from loading at all.

halljoshr avatar Jul 04 '24 13:07 halljoshr