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

Infinite loop when using ServerLoad without components parameter. #138

Open
hasansezertasan opened this issue Dec 29, 2023 · 2 comments
Open

Comments

@hasansezertasan
Copy link
Contributor

I mentioned this at #123.

Example code:

from __future__ import annotations as _annotations

import random
import time

from fastapi import FastAPI
from fastapi.responses import HTMLResponse
from fastui import AnyComponent, FastUI, prebuilt_html
from fastui import components as c
from fastui.events import GoToEvent, PageEvent


def Master(*components: AnyComponent, title: str | None = None) -> list[AnyComponent]:
    return [
        c.PageTitle(text="Lotto Numbers Generator"),
        c.Navbar(
            title="Still Lotto Numbers Generator",
            title_event=GoToEvent(url="/"),
        ),
        c.Page(
            components=[
                *((c.Heading(text=title),) if title else ()),
                *components,
            ],
        ),
    ]


app = FastAPI()


@app.get("/api/", response_model=FastUI, response_model_exclude_none=True)
def components_view() -> list[AnyComponent]:
    return Master(
        c.Div(
            components=[
                c.Heading(text="Lotto Numbers Generator", level=2),
                c.Paragraph(text="Generate lotto numbers for your next game."),
                c.Button(text="Generate a lotto number!", on_click=PageEvent(name="add-number")),
                c.Div(
                    components=[
                        c.ServerLoad(
                            path="/add-number",
                            load_trigger=PageEvent(name="add-number"),
                        ),
                    ],
                    class_name="py-2",
                ),
            ],
            class_name="border-top mt-3 pt-1",
        ),
        title="Quite simple and Understandable Example",
    )


@app.get("/api/add-number", response_model=FastUI, response_model_exclude_none=True)
async def modal_view() -> list[AnyComponent]:
    time.sleep(0.5)
    return [
        c.Paragraph(
            text=f"Your lotto number is {random.randint(1, 99)}!",
        ),
        c.ServerLoad(
            path="/add-number",
            load_trigger=PageEvent(name="add-number"),
        ),
    ]


@app.get("/{path:path}")
async def html_landing() -> HTMLResponse:
    """Simple HTML page which serves the React app, comes last as it matches all paths."""
    return HTMLResponse(prebuilt_html(title="FastUI Demo"))

If you navigate to /, you'll see the ServerLoad event keeps triggering even fi you don't click the button.

@meirdev
Copy link

meirdev commented Dec 30, 2023

It seems the problem is here:

https://github.com/pydantic/FastUI/blob/cec25c61a7cc5a716d05d21039f95be3e8dac0e8/src/npm-fastui/src/components/ServerLoad.tsx#L15C14-L23

Maybe the condition should depend on loadTrigger and not on components:

export const ServerLoadComp: FC<ServerLoad> = ({ path, components, loadTrigger, sse }) => {
  if (loadTrigger) {
    return <ServerLoadDefer path={path} components={components ?? []} loadTrigger={loadTrigger} sse={sse} />
  } else if (sse) {
    return <ServerLoadSSE path={path} />
  } else {
    return <ServerLoadFetch path={path} />
  }
}

@samuelcolvin
Copy link
Member

I'll look soon.

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

No branches or pull requests

3 participants