Why these hicups when using a slider widget in this way?

Below is a snipet showing how I create a widget in a sidebar.
(I do so because I need to share the sidebar and its data in a multiple page app)

The animated gif shows what happens when I used it.
You can see the hicups when chosing a new value.
I need to select twice before the new value is effective.
The same hicups occur with any widget that I tested: text, daterange, selectbox, …

Note that the argument value=self.val is needed when I go for a multipage app where I need to share the selected value with other pages. For a single page app, it can be removed, and the problem disappers.

I don’t understand where this comes from.
And I don’t see how to solve this.

Any idea?

Michel

import streamlit as st

class testClass:
    """A simple test"""
    def __init__(self, val=5):
        self.val = val
        
    def sidebar(self):
        """Adding widget to the sidebar"""
        with st.sidebar:      
            self.val = st.select_slider(r"$\bold{from}$", 
                        options=[0,1,2,3,4,5,6,7,8,9], 
                        value=self.val) 

if not st.session_state:
    st.session_state.test = testClass()
    
st.session_state.test.sidebar()
st.write(st.session_state.test)

ScreenRecording2024-04-01at12.33.35-ezgif.com-video-to-gif-converter

The pattern of x = st.widget(value=x) often causes such hiccups, because of the way that streamlit apps rerun from top to bottom any time that a widget is changed.

The recommended way around this is to use a key on the widget, which makes it so that the value is automatically synced with session_state.

HOWEVER, the problem is that when the widget is gone (like when you switch pages), it is removed from the page. You can trick streamlit into preserving it by doing something that looks pretty silly:

if "val" in st.session_state:
    st.session_state["val"] = st.session_state["val"]

Or, more generally:

for k, v in st.session_state.items():
    st.session_state[k] = v

The key is to put that at the top of every page in a multipage app.

streamlit_app.py

import streamlit as st

if "val" in st.session_state:
    st.session_state["val"] = st.session_state["val"]

with st.sidebar:
    st.select_slider(
        r"$\bold{from}$", options=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], key="val"
    )

st.write(st.session_state.val)

pages/page1.py

import streamlit as st

if "val" in st.session_state:
    st.session_state["val"] = st.session_state["val"]


st.write(st.session_state.val)
1 Like

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.