Update and replace elements
Most Streamlit commands draw something on the screen, and most commands also return an object. What that object is — and what you can do with it — depends on the type of command. Understanding this is the key to updating your app's display in place without triggering a full rerun.
Elements, containers, and widgets
Streamlit commands fall into three categories based on what they return:
Element commands
Commands like st.markdown, st.image, st.dataframe, and st.line_chart draw a single visible element. They return an element object, an object you can use to replace or clear that element later:
You can call .empty() on any element object to clear it from the screen:
Container commands
Commands like st.container, st.columns, st.tabs, and st.empty create regions that hold other elements. They return a container object that you can write into using method calls or context managers:
st.empty is a special container that holds only one element at a time. Each write to an st.empty object replaces the previous content. This makes it the primary tool for in-place updates. For more on containers, see Using layouts and containers.
Widget commands
Commands like st.slider, st.selectbox, st.button, and st.text_input are widgets. They return a Python value like int, str, or bool instead of an abstract Streamlit object. You interact with widget state through st.session_state and callbacks, not by calling methods on their returned values:
For details on how widgets manage state and identity, see Widget behavior.
Widget-mode elements
Some elements can switch into widget mode when configured with interactive parameters. In widget mode, the element either returns its state directly, or its usual element object has state attributes. Elements in widget mode follow widget rules with respect to keys, callbacks, and Session State.
For example, st.dataframe normally returns an element object. However, when you set on_select="rerun", it returns a selection dictionary instead:
Similarly, st.tabs, st.expander, and st.popover become widget-like when you set on_change. They still return container objects, but they also track state, which is available as attributes on the container objects. See Dynamic containers for details.
Replacing and clearing elements
The most common pattern for in-place updates is using st.empty:
To replace a group of elements, nest st.container inside st.empty:
Any element (not just st.empty) supports replacement and clearing. This works because every non-widget Streamlit command returns an element object for the position it occupies in the app:
Updating specific element types
Some elements have specialized update methods beyond replacement:
st.progress
Update a progress bar by calling .progress() on the returned object. Clear it with .empty():
st.status
Update a status container's label, state, and expanded state with .update():
st.toast
Update a toast notification in place by calling .toast() on the returned object:
Appending data with .add_rows()
st.dataframe, st.table, and basic chart elements like st.line_chart support an .add_rows() method that appends data to the element without replacing it. This is useful for streaming data or building up a chart incrementally:
Note
The Streamlit team is evaluating the future of .add_rows(). If you use this method, please share your feedback in the community discussion.
Still have questions?
Our forums are full of helpful information and Streamlit experts.
