Steamlit elements calling OnClick running without click

Using streamlit elements.

My code

def switch_the_page():
    st.switch_page("pages/3_Audience_Demographics_Evals.py")

                
                
mui.Button(
    "To Page",
    size="small",
    variant="text",
    color="secondary",
    #startIcon=mui.icon.Download(),
    style={"color":"#000000", "background":"#FFFFFF"},
    onClick=switch_the_page()
)

I’m trying to put a button on my charts or anywhere within elements and the button shows fine. However, when I add the ‘onclick’ parameter with the switch page function, the page effectively redirects to the page in the switch page call.

But i want to wait for it to be clicked.

There are other topics about the components change in streamlit 1.34.0, I’m using 1.35.0 - and i’ve tried the solution for that. But it seems the onclick does work but doesn’t wait so I think it’s a seperate issue!

I think the problem is that you are calling the function, which evaluates to None,

instead of just passing the function object switch_the_page.

Thank you for your thought. It stops the running immediately, but now when I press the button, or use the same function in a hot key event callback, all it does is reload the entire page without any update.

I’ve even added print statements and st.write in the function and it doesn’t seem to run when clicked.

The workaround is here but now I am getting another error regarding

“Calling st.rerun() within a callback is a no-op.”

Ah yes, trying to switch the page from a callback will fail with that warning:

st.button("Switch page as callback", on_click=st.switch_page, args=("pages/1_one.py",))

Try instead,

if st.button("Switch page as side effect"):
    st.switch_page("pages/1_one.py")

However, I am not sure if the same can be done using mui.Button.

So I’ve managed to get around it with the callback function as

def callback_func(): 
    st.session_state.bar_switch_page_button_clicked = True

Then at top of the code to enable redirection only on the first rerun:

if "bar_switch_page_button_clicked" not in st.session_state:
    st.session_state.bar_switch_page_button_clicked = False

if st.session_state.bar_switch_page_button_clicked:
    # order of these two lines very important
    st.session_state.bar_switch_page_button_clicked = False
    st.switch_page("pages/3_Audience_Demographics_Evals_Bar.py")

Just to add on @edsaac’s response.

Streamlit runs the whole page from top to bottom whenever a refresh is triggered. When an element with a callback triggers a rerun, it runs the callback before running the page. st.switch_page stops the execution and switches to whatever page it references. However, due to limitations on how streamlit works, it is not possible to use st.switch_page inside a callback (that’s what a ‘no-op’ means).