Question: I appear to fundamentally misunderstand how Streamlit's forms and session_state variable work. Form data is not inserted into the session_state upon submit. However, submitting a second time inserts the data. Updating session_state values always requires submitting the form 2 times. I'd like to know  if this is expected behavior if I'm making a mistake if there is a workaround that allows immediate session_state updates on submit  EXAMPLE 1: import streamlit as st # View all key:value pairs in the session state s = [] for k, v in st.session_state.items(): s.append(f"{k}: {v}") st.write(s) # Define the form with st.form("my_form"): st.session_state['name'] = st.text_input("Name") st.form_submit_button("Submit")  When the page loads, the session state is empty: []  After submitting the form once, the session_state contains "name: ". The key has been added, but not the value.  After pressing Submit a second time, the session_state now contains "name: Chris"  EXAMPLE 2: Using a callback function import streamlit as st # View all key:value pairs in the session state s = [] for k, v in st.session_state.items(): s.append(f"{k}: {v}") st.write(s) # Define the form with st.form("my_form"): def update(): st.session_state['name'] = name name = st.text_input("Name") st.form_submit_button("Submit", on_click=update)  When the page loads, the session state is empty: []  After submitting the form once, the session_state contains "name: ". The key has been added, but not the value.  After pressing Submit a second time, the session_state now contains "name: Chris" 

Answer: The critical part to think about is: where are you writing session state values relative to where the widget is? In particular, you are accessing/displaying session state values before the widget. Try this to see what's happening a bit clearer: import streamlit as st st.write(st.session_state) with st.form('my_form'): st.session_state.A = st.text_input('A') st.text_input('B', key='B') st.form_submit_button('Submit') st.write(st.session_state)  You will note for widget A that session state does not update until after the widget. If you want to access data for widget A before widget A, then you end up with your "double submit" problem. For widget B, you can see that session state is correct right away, even when accessed before the widget. What is happening? For a widget (outside of form), when a user makes a change:  User enters a new value Session state associated to the widget's key is updated The page reloads The output of the widget function shows the new value  If you have the output of a widget assign a value to session state instead of setting the key for the widget directly, then that output data cannot be updated until the widget function is executed again and can output that new value. With a form, the same logic applies except that the new value is not registered until the submit button is clicked. Solutions  You can assign a key to a widget directly so that the value is update upon the change, before the page loads. (Or) You can make sure to not access widget data before the widget.  If needed you can use containers to allow you to have the widget logically first in the script but displayed later in the page.