st.toast alerts without rerun duplicates: choosing persistence and dedup strategy
0 reputation · 08 Feb 2021, 17:09 UTC
0 reputation · 08 Feb 2021, 17:09 UTC
I want to surface useful in-app alerts in a Streamlit app using st.toast, without creating notification noise. The alerts are low-priority status events (for example, a background data refresh completing), so they should not block the script, but they also should not reappear every time the user touches an unrelated widget.
From the documentation, st.toast is transient and non-blocking, but the script reruns top to bottom on every interaction, so a toast tied to a condition will fire again on each rerun unless deduplicated. st.session_state flags seem to be the standard guard, but that gives once-per-session behavior, which may hide a condition that clears and later becomes true again. For anything that must stay visible until acknowledged, st.warning or st.error would persist inline instead, so there is a real tradeoff between visibility and noise. There also appears to be no documented way to push alerts outside an active session. Assume a recent Streamlit version; the st.toast signature should be checked against the installed release.
30775 reputation · 08 Feb 2021, 23:57 UTC
To fire an st.toast exactly once per condition occurrence rather than once per session, you must track the state of the trigger rather than the state of the notification. Instead of a simple boolean flag (e.g., toast_shown = True), store a unique identifier or a version timestamp of the event in st.session_state.
By comparing the current event ID against the last recorded ID in the session state, you ensure the toast only triggers when the condition actually changes, allowing it to fire again if the condition clears and recurs.
import streamlit as st
# Assume 'data_version' is a value that changes when a refresh completes
current_version = get_data_version()
if "last_toast_version" not in st.session_state:
st.session_state.last_toast_version = None
if current_version != st.session_state.last_toast_version:
st.toast(f"Data refreshed to version {current_version}")
st.session_state.last_toast_version = current_version
When multiple events occur in a single rerun, batching is the recommended approach. Streamlit's st.toast implementation stacks notifications, but rapid-fire toasts can create visual noise and may be dismissed by the user before they are read.
The decision to switch from st.toast to st.warning or st.error depends on the required user acknowledgment and criticality.
| Feature | st.toast | st.warning / st.error |
|---|---|---|
| Persistence | Transient (disappears) | Persistent (inline) |
| Interruption | Non-blocking | Visual anchor in layout |
| Use Case | Status updates, confirmations | Action required, critical failures |
Switch to persistent elements when the alert contains information the user must see to proceed or when the alert describes a state that requires manual intervention to resolve.
This pattern assumes a recent version of Streamlit where st.toast is available. To verify, initialize your session state key, trigger the condition, and interact with any other widget; the toast should not reappear until the version/ID changes.
Use comments to ask for clarification. Post a solution as an answer.
30,775 reputation · 08 Feb 2021, 18:36 UTC
key Argument Is Not AvailableUnlike most Streamlit widgets, st.toast does not expose a key parameter. Attempting to pass one will raise a TypeError. The only way to control when a toast appears is by guarding the call with state you manage yourself.
st.session_stateStore a unique identifier for each event (e.g., a timestamp or incrementing counter) in st.session_state. Show the toast only when the current identifier differs from the stored one, then update the stored value. This pattern guarantees the toast fires once per event occurrence and can fire again if the event clears and repeats.
import streamlit as st
# Example: a background refresh that produces a new version number
current_version = get_data_version()
# Initialize the session state key
if "last_version" not in st.session_state:
st.session_state.last_version = None
# Fire a toast only when the version changes
if current_version != st.session_state.last_version:
st.toast(f"Data refreshed to version {current_version}")
st.session_state.last_version = current_version
When several status changes happen in a single rerun, concatenate the messages into a single toast or create a “summary” toast. Stacking many individual toasts can overwhelm the UI and may cause newer notifications to be dropped.
Use st.info, st.warning, or st.error when the message requires user acknowledgment, manual dismissal, or should remain visible until addressed. These components stay in the layout until the user clears them, preventing accidental loss of critical information.