Session state with radio buttons not working

Hello,
I am trying to combine session states with radio button selections in the sidebar. Here is the example

import streamlit as st

if 'name' not in st.session_state:
    st.session_state.name = 'Example Name'
    
if 'phone' not in st.session_state:
    st.session_state.phone = '1234'
    
with st.sidebar:
    radio = st.radio(
    "Please select",
    ('Name', 'Phone'))
    
    
if radio == 'Name':
    st.text_input('Enter your name', key='name')
    st.file_uploader('Select a picture', key='file_pic')

if radio == 'Phone':
    st.text_input('Enter phone number', key='phone')

Two problems:

  1. the phone number dont get initialized with the key.
  2. inserted Name, uploaded file and phone number are not saved when switching between radio button options in the sidebar.

I would like that entered values get stored when switching between the radio buttons.
using Streamlit v1.13.0
Thanks,
Robert

Hi,

This seems to be a common issue amongst new Streamlit users, so I wrote a mini-tutorial app to explain how widgets are used with initialized values and how to make them stick using session state and callbacks.

There are three ways: (1) the most basic where the initial value is not given but the widget is always reset, (2) where it’s initialized but there are issues getting the return value to stick, and finally (3) overcoming all issues with session state and callbacks. (I think the issue in the second case is a Streamlit bug :thinking:).

You can find my tutorial here.

HTH,
Arvindra

The docs say

If you don’t call a widget function in a script run, we neither store the widget state nor render the widget. If you call a widget function with the same arguments later, Streamlit treats it as a new widget.

This means that even if the widget has an explicit key, that key is deleted from session_state when it is not instantiated.

Apparently this behavior can be overridden by unconditionally assigning a value to the session_state item. This is not documented as far as I know so I guess it might stop working at any moment but so far it works.

Unfortunately you cannot assign a value to a file_uploader (or its assiciated key), you’ll need to keep the file in yet another key so that it is available in your code even after the widget is reset.

import streamlit as st

# unconditionally assign values to 'name' and 'phone'
st.session_state.name = st.session_state.get('name', 'Example Name')
st.session_state.phone = st.session_state.get('phone', '1234')

with st.sidebar:
    radio = st.radio(
    "Please select",
    ('Name', 'Phone'))
    
    
if radio == 'Name':
    st.text_input('Enter your name', key='name')
    # store the uploaded file when it is not None.
    if st.file_uploader('Select a picture', key='file_pic'):
        st.session_state.uploaded_file = st.session_state.file_pic
    # show that the file is stil there
    st.write(st.session_state.get('uploaded_file', None))

if radio == 'Phone':
    st.text_input('Enter phone number', key='phone')

Thanks asehmi and Goyo! This helps me a lot to understand how session states work.
Robert

1 Like

I tried your code and it works fine, however I still would like to solve the following problems considering the file_uploader:

  1. After uploading the file and directly deleting it afterwards, the other variable (‘st.session_state.uploaded_file’) don’t get deleted as well.
  2. It would be nice to have a way to delete the uploaded file after file uploader is initiated again but still a file is stored in ‘st.session_state.uploaded_file’. In other words: after uploading a file and switching the radio buttons I would like to be able to delete the uploaded file.

Thanks in advance,
Robert

I don’t think I understand what you want. What sequence of user actions lead to the undesired behavior you are seeing?