Hey @posey22
Iām having a hard time understanding your question, but I totally get that UI behavior is really hard to describe in words
So for example, if I use a slider to choose a value that then multiplies a column in a dataframe when I press a button to submit that calculation, if I go to submit using a button somewhere else that gets reset. I would like the results of that button press to persist. In other words, I want that button value to stay True.
Weāve actually been thinking about the āsubmit buttonā scenario lately, and considering whether we should provide a new API just for this case. For example, maybe there should be a way to specify a āwidget groupā whose values only get set to the server when āsubmitā is pressed.
But to better design this API, it would be great to get a bunch of ātoy examplesā of what people would like to do with it. So if you can come up with a tiny script that exemplifies what you need, that would be amazing!
Iām assuming what youāre working on with SessionState fixes this issue?
Streamlit reruns your script fresh from the top every time you change the value of a widget. But sometimes you want to keep some values around in between runs (for example, when incrementing a variable, when doing incremental manipulations of a dataset, etc.).
Thatās where SessionState comes in. It lets you persist data across reruns.
If I hit the button 5 times x will always be 1 if it started by 0.
Hmmmā¦ thatās not supposed to happen with the code snippet I pasted above. Did you try running it? Or perhaps youāre reacting to the API used for the SessionState prototype? In case itās the latter, hereās a quick explanation of how the prototype API works:
When you do this:
state = SessionState.get(x = 100)
if st.button('Increment x'):
state.x += 1
st.write("Current value of x:", state.x)
Hereās what happens behind the scenes:
- When a user opens a new browser tab with your Streamlit app, Streamlit runs the script above from top to bottom. When it reaches the
SessionState.get()
statement, it checks whether that given user already has a āsessionā object associated with it. If not, then it initializes thestate
value ofstate.x
to100
. Note that this only happens once per user! - When the user clicks the āIncrement xā button, Streamlit reruns your script from top to bottom. This time, the
SessionState.get()
statement will return that userās existing SessionState object. - Since the user clicked the button, the
if
condition will beTrue
, sostate.x
will increment by1
andst.write()
will write āCurrent value of x: 1ā to the app. - If the user clicks āIncrement xā again, Streamlit will rerun your script from top to bottom. Now
SessionState.get()
will return a state object wherestate.x
is set to1
. So this time the code inside theif
condition will increment it to2
.
And so on!
Iāve thought of it two ways, either the initialization step could be performed once, or the updated variable could be cached. I too am looking for this functionality.
As described above, your first idea is exactly what we do: the initialization step is only performed once
This discussion is super valuable, by the way! It makes it clear that API of the SessionState
prototype is not very clear. One way to improve it would be to rename the get()
method to something like get_or_set
or get_existing
or something like that.
Also: with respect to buttons in general, in addition to the āwidget groupā API I mentioned at the top, weāre also considering another API where buttons are allowed to run small callback functions before a script executes ā among other ideas. For more on this, check out this thread: How to evolve complex state (e.g., annotate data)?