← Back to list

How (not) to create a responsive form in Streamlit?

Diving into the limitations of st.form, or when does st.form not perform as responsively as expected?

UnicornOnAzur in Top Python Libraries · 2026-07-20 12:41 · 5 claps · 1.8 min read
#streamlit #python-programming #streamlit-app-deployment #session-state #python-control-flow
Open on Medium ↗
Wiki topics: 💻 · Programming

How (not) to create a responsive form in Streamlit?

Diving into the limitations of st.form, or when does st.form not perform as responsively as expected?

With the addition of st.form¹, Streamlit’s user experience has improved significantly. While I was building an app recently, I discovered an “anti-pattern” regarding the use of callback functions with inputs from st.form. When the form is submitted, the most recent values are not updated yet, and you need to press the button twice. I’m not the first to encounter this (see here, here or here). That’s why I’m sharing this story for future reference and to help others learn from it.

Image created by magicstudio

Image created by magicstudio

When doesn’t it work?

If you create a basic form and want to use the results in your callback function, in the setup below you’ll encounter that the variables are not updated before the submit button is pressed. The MWE shown below will show you that your selection is not shown when you press the button the first time. Only on the second press of the button is the updated value shown.

import streamlit as st

with st.form("form"):
    s = st.segmented_control("Slide", options=range(5))
    st.form_submit_button("Submit", on_click=st.write, args=(s, ))

So why doesn’t it work? Apparently when storing the output of widgets in variables these are not updated when the submit button is pressed.²’³’⁴

A simple change to using the Session State will make it work.

import streamlit as st

def callback(key: str):
    st.write(st.session_state[key])

with st.form("form"):
    st.segmented_control("Slide", options=range(5), key="s")
    st.form_submit_button("Submit", on_click=callback, args=("s"))

What works?

To show what works I’ve look at the options/choices you can make when created a form:

  • Using the with statement or the direct assignment;
  • Using variables or keys for the output;
  • Using a callback function, via on_click, or a function called on an if-statement³.

This gives eight possible combinations to make a form. In this app I showcase how all combinations work as long as the widget state is not stored in a variable together with on_click. In essence, the options for forms mentioned in the documentation³’⁵ work.

This story is my way to share my coding experience and the lessons I learned, and to document my solutions. All claps, comments, and highlights are appreciated, as well as sharing the story. For more code and my other links see: https://github.com/UnicornOnAzur/.

[1] https://discuss.streamlit.io/t/introducing-submit-button-and-forms/12401

[2] https://discuss.streamlit.io/t/date-input-not-working-on-form-submit/34740

[3] https://docs.streamlit.io/develop/api-reference/execution-flow/st.form

[4] https://discuss.streamlit.io/t/using-form-submit-button-with-callback-does-not-capture-arg-from-other-form-input/81134

[5] https://docs.streamlit.io/develop/concepts/architecture/forms


메타데이터
post_id
d487bb0836a1
slug
how-not-to-create-a-responsive-form-in-streamlit-d487bb0836a1
url
https://medium.com/top-python-libraries/how-not-to-create-a-responsive-form-in-streamlit-d487bb0836a1
canonical_url
https://medium.com/top-python-libraries/how-not-to-create-a-responsive-form-in-streamlit-d487bb0836a1
author_url
https://medium.com/@unicornonazur
status
ok
fetched_at
2026-08-03 23:05:12