Fragments, dialogs and controlling reruns

Streamlit · Advanced · 14 min

Full-script reruns get slow in big apps; fragments make interactions local and enable live-updating panels.

A fragment is a function decorated with @st.fragment. When a widget inside the fragment changes, Streamlit reruns only that function, not the whole script. Widgets outside still trigger full reruns.

@st.fragment
def filters_and_chart():
    metric = st.radio("Metric", ["visits", "signups"])
    st.line_chart(load_data()[metric])

Use fragments for self-contained parts of a page: a chart with its own controls, a form-like panel, a table editor. Pass run_every="10s" to rerun the fragment on a timer, which gives live dashboards without a full page refresh.

Things to know:

  • Values computed inside a fragment are not visible to the rest of the script until a full rerun; share them via session state.
  • A fragment's elements are redrawn in place on each fragment rerun. Its widgets must be drawn in its own body, not into containers created outside it.
  • st.rerun() triggers an immediate rerun of the whole app; inside a fragment, st.rerun(scope="fragment") reruns just the fragment.

Dialogs are fragments shown as a modal: decorate a function with @st.dialog("Title") and call it, typically from a button. Widgets inside the dialog rerun only the dialog; call st.rerun() to close it and refresh the app once the user confirms.

st.stop() ends the current run immediately, useful for guards such as "please upload a file first".

Example

import time
import streamlit as st

if "items" not in st.session_state:
    st.session_state.items = ["apples"]

st.write("Full app run at", time.strftime("%H:%M:%S"))

@st.fragment(run_every="5s")
def live_panel():                      # reruns alone, every 5 seconds
    st.metric("Server time", time.strftime("%H:%M:%S"))

@st.dialog("Add item")
def add_item():
    name = st.text_input("Item name")  # typing reruns only the dialog
    if st.button("Save") and name:
        st.session_state.items.append(name)
        st.rerun()                     # close dialog, refresh the whole app

live_panel()
if st.button("Add item"):
    add_item()
st.write(st.session_state.items)
if not st.session_state.items:
    st.stop()                          # nothing below runs

Remember

  • @st.fragment reruns only that function when its own widgets change
  • run_every refreshes a fragment on a timer for live views
  • @st.dialog builds modals; st.rerun() and st.stop() control execution

Watch out for

  • Expecting values computed inside a fragment to update the rest of the page without a full rerun.

Check yourself

  1. Inside `@st.fragment def panel():` a user moves a slider that belongs to the fragment. What reruns?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: docs.streamlit.io/develop/concepts/architecture/fragments