When choosing from the multiselectbox below, I find that I have to click the options twice in order for it to register in the streamlit application.
By default the select shows the years 2017-2019.
If I then click ‘2016’ it shows 2016-2019, correctly.
If I then click ‘2015’ it show 2016-2019 once again.
If I then click ‘2015’ once again, it shows 2015-2019, which is correct.
I want the multiselect to default to the latest y1-input always, since the application has multiple pages, which the user navigates in between.
This is some bugginess around the SessionState implementation, and how it interacts with Streamlit’s rerun logic. As a workaround, you can do something like this:
import streamlit as st
from streamlit.ScriptRequestQueue import RerunData
from streamlit.ScriptRunner import RerunException
last_y1 = session_state.y1
session_state.y1 = st.multiselect(
"Select year(s)",
['2013', '2014', '2015', '2016', '2017', '2018', '2019'],
session_state.y1)
if last_y1 != session_state.y1:
raise RerunException(RerunData(widget_state=None))
That RerunException will force Streamlit to re-execute your script whenever the session_state is updated.
(This is a temporary solution; we intend to “officially” implement SessionState in an upcoming release.)
Thank you Tim, that worked out exactly as intended!
I will look forward to the “official” implementation of SessionState in the future, but this will do for now
I seem to have the same problem with a text area. The solution proposed here does not work for me, I guess as I am doing other things with “session” variables here as well.
My current solution is that I present users the message that their next edit will be ignored, which works for a while but is not a really viable route for the future.
Just FYI to make clear that it does not only affect Multiselect widgets.
This still seems to be a problem. I have a st.number_input in my script, and it only works correctly on every second press of the step buttons. Every other time it will just reset to the previously displayed value.
I am using my own implementation of something like SessionState, however mine saves the state to the host machine as a .yaml file, because I don’t intend on using the server via the network. Maybe I made the same mistakes as the SessionState creators, or it is a bug in streamlit itself?
Is there a way to adapt @tim 's workaround with the RerunException in such a way that it only reruns the widgets after the thing that was changed? For me it seems to rerun the entire script every time, even if I only change something at the bottom of the page.
I am using the official SessionState but I still encounter this issue for both selectboxes and text_input (version 0.84.1).
The flow is that I load a data set and the first row. The sidebar widgets get populated with the features from the row and the main area shows the observed label and the prediction. The user can change the features and see how it affects the prediction. But if the user tries to change the same feature multiple times then the 2nd, 4th, 6th […] time doesn’t change the feature . Only in a row though. Change feature1, then feature2, then feature1 is fine.
When I load a row I put the features into dictionary in st.session_state['data'] (if it doesn’t already exist). Then I point the widgets at the dictionary:
for cat in categorical:
cat_values = sorted(df[cat].unique())
st.session_state['data'][cat] = st.sidebar.selectbox(cat,
options=cat_values,
index=cat_values.index(st.session_state['data'][cat]))
for txt in text:
st.session_state['data'][txt] = st.sidebar.text_input(txt,
value=st.session_state['data'][txt])
That way changing a value doesn’t revert the value in another field. I have buttons for Next, Previous, Random and clicking any of them deletes st.session_state['data'] and it gets recreated with the features from the new row. I see that I could use keys on the widgets but this is code-wise really clean. And I don’t see why it should prevent me from changing the same widget twice in a row (maybe something with hashing?).
Thank you. I see what you mean about using keys for widgets but I don’t know how I would repopulate all the widgets with the new data when I load a new line…
EDIT: Oh wait, I think I see it. I can write directly into the state for that key without damaging anything, right? So if I have a function that goes st.session_state['feature'] = new_value then I should be good. I think. Hope.
EDIT2: I anyone has an example app I would be grateful. This doesn’t feel like I’m writing the code as intended.
import streamlit as st
if 'sel_key' in st.session_state : # do not run this the first time
st.write(f'the selected item is: {st.session_state["sel_key"]}')
st.selectbox('test me',(1,2,3),index=1,key='sel_key') # no explicit session_state here!
Quick update: I gave up on this. Using widget keys I couldn’t figure out how to get the widgets populated correctly when I loaded a new line (I would get the first index in a selectbox and I’m pretty sure that the text_input widgets would just never change).
I decided that writing a caveat and moving on was a better use of my time. It’s more important to see the predictions, observed labels, and features than changing the feature values a bunch of times.
Thank you for your time and input ksxx and sorry I couldn’t get it to work (and sorry I don’t have time to write a minimal reproducible example that I could share).
I’ve faced the same issue in several multiselect inputs: I have to change available lists for the next one based on previous select and moreover keep all selections after rerun. I was trying to keep everything in st.sessions_state[‘my_own_dict’][‘some_filter_key’] but it worked not each time. Keeping all in form with submit button also did nothing to problem. But after I’ve just generated keys for each form and asked for value in session_state to load as default value. Everything seems to be ok, even within submit form.
Nevertheless session_state with not key values still has problems.
I have a similar problem, namely I have an app which consists of several pages and I want to save the defaults for the multiselect widget in session state so that it is always up to date.
I have to click the options in the multiselect widget 2 times so that it is transferred to the session state.
I have already tried it via callback functions, but I must also pass the current value of the widget, which is not possible as far as I know.
for columns in st.session_state['cardinal']:
for column in columns:
st.session_state.default[column]
st.session_state.default[column] = st.multiselect(f'{column}', options_cardinal, default=st.session_state.default[column])
Is there any way to use session state in the default options in widgets and keeping it up to date?
Thanks in advance!
I’m still meeting the same problem when I tried both Streamlit 1.24 and 1.25. Also refer this Streamlit Docs Widget update for every second input. Here is my code:
if 'features_chosen' not in st.session_state:
st.session_state.features_chosen = None
st.multiselect("Which features would you like to select?", features, st.session_state.features_chosen, key="features_selectbox")
st.session_state.features_chosen = st.session_state['features_selectbox']
I need the value of st.session_state.features_chosen to be persisted. Now for selecting or deselecting any option, it sometimes takes effect by one time, most of the time it need twice actions.
Can someone help me to solve it please? Many thanks!
Thank you @Goyo ! I create a ‘on_change’ callback function from my last line of code above, it works now. But comparing to st.multiselect, st.selectbox doesn’t need this callback setting to let the change take effect, it works immediately, I don’t know the reason behind.
You cannot do the same thing that you are doing here with selectbox() because you cannot pass a default value. Depending on what you do exactly it may work as you expect or not. Different widgets can show this kind of problem in different circumstances, but the advice to use callbacks to change state in response to user actions is valid for all widgets.
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.