posit-dev / py-shiny

Shiny for Python
https://shiny.posit.co/py/
MIT License
1.3k stars 78 forks source link

UI function not re-evaluated on browser refresh #635

Closed vnijs closed 1 year ago

vnijs commented 1 year ago

In discussion with @schloerke at the issue below it seems we tripped over a bug in shiny-for-python. Although this is just one example, I expect it would also impact things like restoring state after an app is disconnected or there is a browser refresh

https://github.com/rstudio/py-shinyswatch/issues/11#issuecomment-1646973036

In the below app_ui isn't called on browser restart.

from shiny import App, Inputs, Outputs, Session, ui, reactive, render
import shinyswatch

if "theme" not in globals():
    print("Define theme dictionary. Was not in globals()")
    theme = {"theme": "superhero"}

def app_ui():
    print("ui function was called")
    return ui.page_fluid(
        shinyswatch.get_theme(theme.get("theme", "superhero")),
        ui.tags.script(
            """
            Shiny.addCustomMessageHandler('refresh', function(message) {
                window.location.reload();
            });
            """
        ),
        # ui.input_select(
        #     id="select_theme",
        #     label="Select a theme:",
        #     selected=theme.get("theme", "superhero"),
        #     choices=["superhero", "darkly", "sketchy"],
        # ),
        ui.output_ui("ui_select_theme"),
    )

def server(input: Inputs, output: Outputs, session: Session):
    print("server function was called")
    print(theme.get("theme", "superhero"))

    @reactive.Effect
    @reactive.event(input.select_theme, ignore_none=True)
    async def set_theme():
        if input.select_theme() != theme.get("theme", "superhero"):
            theme["theme"] = input.select_theme()
            await session.send_custom_message("refresh", "")
        # ui.update_select("select_theme", selected=theme.get("theme", "superhero"))

    @output(id="ui_select_theme")
    @render.ui
    def ui_select_theme():
        return (
            ui.input_select(
                id="select_theme",
                label="Select a theme:",
                selected=theme.get("theme", "superhero"),
                choices=["superhero", "darkly", "sketchy"],
            ),
        )

app = App(app_ui(), server, debug=False)
schloerke commented 1 year ago

App UI is being rendered before being sent to App.

Closing and giving more explanation in rstudio/py-shinyswatch#11