New to streamlit here and enjoying it. I’m hoping someone could explain button logic for me, and the differences between using callbacks vs the if button_pressed idioms.
In short, under my beginner reading of the tutorial, after a button press the entire script is re-run, and so I expected the two idioms to behave differently. However, if I implement a counter using the two different idioms, I find that the if button_pressed idiom leaves any references to the counter variable before the button press (printed out in the example below) lagging behind. For my application this is undesirable, as I would like the variable to be consistent throughout the entire page. (To be precise, I am actually using a form_submit_button, which has the same behavior as the minimal example below)
So I know what I need to do to get my desired behavior, but was wondering if someone could explain the flow of logic for me, why the two versions below differ, and how experimental_rerun() fixes things (which I have also verified)
Thanks!
Steps to reproduce
Version 1, lagged behavior:
import streamlit as st
if "x" not in st.session_state:
st.session_state["x"] = 1
st.session_state.x
def add():
st.session_state.x += 1
st.session_state.x
submitted = st.button("Submit")
if submitted:
st.session_state.x += 1
#st.experimental_rerun() # Adding this line gives the same behavior as using callback
st.session_state.x
behavior (lagged behavior):
0
[button]
1
Version 2:
import streamlit as st
if "x" not in st.session_state:
st.session_state["x"] = 1
st.session_state.x
def add():
st.session_state.x += 1
st.session_state.x
submitted = st.button("Submit",on_click=add)
st.session_state.x
Page reloads with the button widget returning True
st.session_state.x is shown twice (not yet changed)
Enter the conditional if submitted and the value is incremented
st.session_state.x is shown again, reflecting the incremented value
In version 1, with reload:
Click the button
Page reloads with the button widget returning True
st.session_state.x is shown twice (not yet changed)
Enter the conditional if submitted and the value is incremented
Rerun the page (which happens so fast you don’t see point 3.
Page now loads with the button widget returning False
You get st.session_state.x shown all three times, reflecting the incremented value
In version 2,
Click the button
Page begins reloading but before it starts executing, it is prefixed with the callback.
Hence the value is incremented
Then the rest of the page loads (button happens to be True at this point, but not relevant)
You get st.session_state.x shown all three times, reflecting the incremented value
The key is that the callback happens before the page loads. If you use the if st.button(...) construct, then the code nested in the conditional doesn’t execute until you’ve reloaded the page to that point. If you have anything on the page before the button that needs to use the incremented value, you need the experimental rerun in this case. If you were to only use the value after the button, you could get away without the experimental rerun.
Note: You can use containers to change the order things display to be different from the order they appear in code. It’s the order in code that dictates the need for the rerun or not (if not using a callback). Hence you could code a button at the top of your script, but display it at the bottom with a slick arrangement of containers.
Thanks for stopping by! We use cookies to help us understand how you interact with our website.
By clicking “Accept all”, you consent to our use of cookies. For more information, please see our privacy policy.
Cookie settings
Strictly necessary cookies
These cookies are necessary for the website to function and cannot be switched off. They are usually only set in response to actions made by you which amount to a request for services, such as setting your privacy preferences, logging in or filling in forms.
Performance cookies
These cookies allow us to count visits and traffic sources so we can measure and improve the performance of our site. They help us understand how visitors move around the site and which pages are most frequently visited.
Functional cookies
These cookies are used to record your choices and settings, maintain your preferences over time and recognize you when you return to our website. These cookies help us to personalize our content for you and remember your preferences.
Targeting cookies
These cookies may be deployed to our site by our advertising partners to build a profile of your interest and provide you with content that is relevant to you, including showing you relevant ads on other websites.