New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Session.state not working correctly with sliders #3925
Comments
I have a similar issue, though with some differences: The structure is approx as follows: # page 1
a = st.multiselect(A, ...)
# page 2
B = f(a)
b = st.multiselect(B, ...)
Edit: Based on the last point I looked at the release notes again and there was a change related to session state:
I will try to find out how this relates to my issue (it's not obvious as the |
Hey @steeley and @oerpli. Thanks for the issue! @oerpli is correct, that we did make some adjustments to session state, and specifically widgets in this case. When widgets disappear from the page, we clear out their value in session state. If you want to maintain this functionality, I would update a variable in session state in a callback. I believe the following code would work. if 'level_1' not in st.session_state:
# Initialize to the saved value in session state if it's available
if 'level_1_slider' in st.session_state:
st.session_state.level_1 = st.session_state.level_1_slider
else:
st.session_state.level_1 = 1
st.session_state.level_1_slider = 1
def handle_change():
st.session_state.level_1 = st.session_state.level_1_slider
st.slider('level1', min_value=0, max_value=10, on_change=handle_change, key="level_1_slider")
st.write('level_1 = ', st.session_state.level_1) This might not be the most ideal for your use case, but we have found most people wanting to isolate widget values in session states as they navigate to new pages. Placing the value into an "independent" variable on session state keeps things maintained across pages. Feel free to comment if you need any extra help. |
thanks - that is one way of working around the issue. |
In this case, the counter variable is not attached to the button because it is updating a different variable, a consistent behavior. Note the session state variable for the counter has an independent name and not the same as the button's key (which is not supplied). We debated a lot about the implications of different approaches but felt that this functionality creates the same consistency under the hood. It led us to write more about this behavior in our docs. |
ok thanks for the info. |
The sample you provided did work @kmcgrady , thanks. I adapted it to reduce the boilerplate a bit, maybe someone has further ideas how it could be improved: # Helper function that initializes session_state variables
def persist_state(key, default_value=None, set_default=False):
# Init persist dict
if "persist" not in st.session_state:
st.session_state["persist"] = dict()
# Init key
if key not in st.session_state["persist"]:
# Initialize to the saved value in session state if it's available
if key in st.session_state:
st.session_state["persist"][key] = st.session_state[key]
elif default_value is not None:
st.session_state["persist"][key] = default_value
st.session_state[key] = default_value
# Generic callback function (curry with lambda & pass)
def __handle_change(key):
st.session_state["persist"][key] = st.session_state[key]
default = st.session_state["persist"].get(key)
return {
"on_change": lambda: __handle_change(key),
"key": key,
# only include default arg if set_default=True as some forms don't support default
**{"default": default for x in [set_default] if set_default},
}
# Usage
m = st.multiselect("Select from M", M,
**persist_state("m", [], set_default=True)
) |
If interested, here's a slightly different solution not relying on |
hi @okld i have another problem about file_uploader, When I apply file_uploader and display the contents of the csv that I uploaded on page A, and I go to page B and when I switch to page A then the file I uploaded earlier will disappear and also not display the contents of the csv |
Hi @riyosan, it seems that it is not possible to set a default value for PS: I noted that you posted the same issue on crxi/multipage_streamlit#1 but I will answer it here as this seems more of a streamlit restriction and not something multipage_streamlit can get around. |
Summary
sliders with values in session.state always go back to the initial value between multiple pages even if their session.state value is updated. This was not an issue prior to version 1.0.
Steps to reproduce
create a simple app with 2 pages, a main app with a side bar with radio buttons to select each.
add a session.state counter button on each to show this works ok.
Code snippet: main streamlit app:
Code snippet: page 1
Code snippet: page 2
If applicable, please provide the steps we should take to reproduce the bug:
change the slider and counter on page 1
go to page 2, change the slider and counter on page 2
go back to page 1 - counter value ok, slider value back to default
go back to page 2 - counter value ok, slider value back to default
NOTE: selecting 'rerun' from the menu seems ok - all session state data is intact and sliders do not get reset.
Expected behavior:
slider values and visual position should update to new value.
Actual behavior:
slider values and visual position not update to new value.
Is this a regression?
That is, did this use to work the way you expected in the past?
Yes
Debug info
Other info::
I tried adding a slider and storing its session.state to your multiapp session.state demo ( release notes, tic tac toe etc)
and got the same error.
The text was updated successfully, but these errors were encountered: