Mini-tutorial: Initializing widget values and getting them to stick without double presses

I would expect a double click needed in case 2.

  1. Say the widget is in sync: it has it’s initial value and is outputting its initial value.
st.session_state.A2 = st.number_input(
    label="What is A2?",
    min_value=0, max_value=100,
    value=st.session_state.A2,
    key='num_A2'
)
  1. You click on the widget, so st.session_state.num_A2 is updated instantly and page reloads.
  2. After reloading, st.session_state.A2 is updated, as an output from the widget (namely after the widget is mounted).
  3. On the next click, st.session_state.num_A2 is again updated and the page reloads.
  4. Now although we have a value in st.session_state.num_A2 which should be correct, the widget sees a new initial value in st.session_state.A2 that it didn’t see before, hence Streamlit goes “New Widget!”
  5. Now since the real value we want is stored in a key associated to a widget that Streamlit thinks has been destroyed, what do we get? “Streamlit doesn’t connect back to widgets of the same key if it thinks it’s a different widget.”
    • This is an ongoing issue with multipage use cases. Slap in some key preservation at the top (see below), and presto! You’ve just convinced Streamlit that the value associated to the key does not need to be discarded in the cleanup process.
    • “Well that widget is gone. Let’s get rid of that key value. Oh look, a new widget. No, I don’t already have this key. Let’s make one.”
    • “What widget? This key isn’t associated to a widget. It was just manually written at the top of the page. Oh look! A new widget and I already have a key of the same name. I’ll connect that up right now.”

My so-called “key preservation” for the top of the script:

if 'num_A2' in st.session_state:
    st.session_state.num_A2 = st.session_state.num_A2
7 Likes