I have a simple streamlit app that displays text from a cell in a pandas data frame. There are buttons to navigate between entries. The user will then pick an element from a select box. Their choice should be stored when they move to the next example, and be displayed accordingly if they move back.
My problem is resetting the selectbox to it’s default state / changing it to the previously selected value. However if I attempt to access the select box from session state I will crash with:
raise StreamlitAPIException(streamlit.errors.StreamlitAPIException: st.session_state.selected_value cannot be modified after the widget with key selected_value is instantiated.
I’ve created a minimal app to reproduce the error:
streamlit 1.41.1
Python: 3.11.11
import streamlit as st
import pandas as pd
@st.cache_data
def load_data():
return pd.DataFrame({'a': list('abc')})
df = load_data()
if "row_index" not in st.session_state:
st.session_state.row_index = 0
if "selections" not in st.session_state:
st.session_state.selections = {}
if "selected_value" not in st.session_state:
st.session_state.selected_value = "-"
# Function to reset selection before rerunning the script
def reset_selection():
st.session_state.selected_value = "-"
# Function to go to the next row
def next_row():
st.session_state.selections[st.session_state.row_index] = st.session_state.selected_value
if st.session_state.row_index < len(df) - 1:
st.session_state.row_index += 1
reset_selection()
st.rerun() # Force re-run of the app to apply changes
# Function to go to the previous row
def prev_row():
st.session_state.selections[st.session_state.row_index] = st.session_state.selected_value
if st.session_state.row_index > 0:
st.session_state.row_index -= 1
reset_selection()
st.rerun() # Force re-run of the app to apply changes
# Display row content
row_text = df.iloc[st.session_state.row_index, 0] # Assuming text is in first column
st.write(f"**Text:** {row_text}")
# Dropdown selection
selected_value = st.selectbox(
"Select a value:",
["-", "A", "B", "C"],
key="selected_value",
)
# Navigation buttons
col1, col2 = st.columns(2)
with col1:
if st.button("Previous"):
prev_row()
with col2:
if st.button("Next"):
next_row()
# Display stored selections
st.write("### Stored Selections:")
st.write(st.session_state.selections)
Thanks for your reply. Basically what I want to build is part of an annotation system. The user should be able to navigate through texts and select them into categories. For selecting the categories I use the select box. Now what I want to accomplish is that when you go to the next record, it’s rest to it’s default value. If the user goes to a record they already worked on the selectbox should indicate what they chose in the past. Thus i wanted to change the state of the widget. But I think I can make your solution work, by additionally checking if a value was stored in the past.
But generally, you are not supposed to edit the state of a widget from another point of the code?
Yes I added the check and it works for me (code below) ! You are not supposed to update the session_state value associated with a widget : here is what the docs says :
import streamlit as st
import pandas as pd
@st.cache_data
def load_data():
return pd.DataFrame({"a": list("abcdef")})
df = load_data()
if "row_index" not in st.session_state:
st.session_state.row_index = 0
if "selections" not in st.session_state:
st.session_state.selections = {}
if "selected_value" not in st.session_state:
# Setting the value to the saved value or resetting to "-"
st.session_state.selected_value = st.session_state.selections.get(
st.session_state.row_index, "-"
)
# Function to reset selection before rerunning the script
def reset_selection():
del st.session_state.selected_value
# Function to go to the next row
def next_row():
st.session_state.selections[st.session_state.row_index] = (
st.session_state.selected_value
)
if st.session_state.row_index < len(df) - 1:
st.session_state.row_index += 1
reset_selection()
st.rerun() # Force re-run of the app to apply changes
# Function to go to the previous row
def prev_row():
st.session_state.selections[st.session_state.row_index] = (
st.session_state.selected_value
)
if st.session_state.row_index > 0:
st.session_state.row_index -= 1
reset_selection()
st.rerun() # Force re-run of the app to apply changes
# Display row content
row_text = df.iloc[st.session_state.row_index, 0] # Assuming text is in first column
st.write(f"**Text:** {row_text}")
# Dropdown selection
selected_value = st.selectbox(
"Select a value:",
["-", "A", "B", "C"],
key="selected_value",
)
# Navigation buttons
col1, col2 = st.columns(2)
with col1:
if st.button("Previous", disabled=st.session_state.row_index == 0):
prev_row()
with col2:
if st.button("Next", disabled=st.session_state.row_index == len(df)):
next_row()
# Display stored selections
st.write("### Stored Selections:")
st.write(st.session_state.selections)
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.