CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-streamlit

A faster way to build and share data apps

Overview
Eval results
Files

state-management.mddocs/

State Management

Session state, query parameters, and context management for maintaining application state across interactions. Streamlit provides powerful state management capabilities that persist data between script reruns.

Capabilities

Session State

Persistent state management that survives script reruns, enabling stateful applications.

session_state: SessionStateProxy

Session state acts like a dictionary that persists across app reruns. Any data stored in session state will be available in subsequent reruns until the session ends.

Key Properties:

  • Persistence: Values persist across script reruns
  • Dictionary-like: Supports standard dict operations (get, set, del, keys, etc.)
  • Widget Integration: Automatically syncs with widget values when key parameter is used
  • Initialization: Values can be initialized on first access

Example usage:

# Initialize session state
if "count" not in st.session_state:
    st.session_state.count = 0

# Access and modify state
if st.button("Increment"):
    st.session_state.count += 1

st.write(f"Count: {st.session_state.count}")

# Store complex data
if "data" not in st.session_state:
    st.session_state.data = {"users": [], "settings": {}}

# Widget state integration
name = st.text_input("Name", key="user_name")
# st.session_state.user_name now contains the input value

# Callback functions with state
def update_data():
    st.session_state.data["last_update"] = datetime.now()

st.button("Update", on_click=update_data)

Common Patterns:

# Conditional initialization
if "initialized" not in st.session_state:
    st.session_state.initialized = True
    st.session_state.user_data = load_user_data()

# Page state management
if "current_page" not in st.session_state:
    st.session_state.current_page = "home"

# Multi-step forms
if "form_step" not in st.session_state:
    st.session_state.form_step = 1

# Data caching in state
if "processed_data" not in st.session_state:
    st.session_state.processed_data = expensive_computation()

Query Parameters

URL query parameter management for shareable and bookmarkable app states.

query_params: QueryParamsProxy

Query parameters provide a way to encode app state in the URL, making it possible to share specific app states or bookmark particular views.

Key Properties:

  • URL Integration: Automatically syncs with browser URL
  • Shareable: URLs can be shared to recreate app state
  • Dictionary-like: Standard dict operations for parameter access
  • Type Handling: All values are strings (conversion needed for other types)

Example usage:

# Read query parameters
params = st.query_params
page = params.get("page", "home")  # Default to "home"
user_id = params.get("user_id")

# Set query parameters (updates URL)
st.query_params["page"] = "dashboard"
st.query_params["filter"] = "active"

# Multiple parameters
st.query_params.update({
    "view": "table",
    "sort": "name",
    "order": "asc"
})

# Clear specific parameter
if "temp_param" in st.query_params:
    del st.query_params["temp_param"]

# Clear all parameters
st.query_params.clear()

# Type conversion (all query params are strings)
if "page_num" in st.query_params:
    page_num = int(st.query_params["page_num"])
else:
    page_num = 1

Common Patterns:

# Page routing with query params
page = st.query_params.get("page", "home")

if page == "home":
    show_home_page()
elif page == "data":
    show_data_page()

# Filter state in URL
filters = {
    "category": st.query_params.get("category", "all"),
    "status": st.query_params.get("status", "active"),
    "sort": st.query_params.get("sort", "name")
}

# Update URL when filters change
if st.selectbox("Category", options, key="cat_filter") != filters["category"]:
    st.query_params["category"] = st.session_state.cat_filter

# Shareable dashboard state
st.query_params.update({
    "chart_type": selected_chart,
    "date_range": f"{start_date}_{end_date}",
    "metrics": ",".join(selected_metrics)
})

Context Information

Access to current execution context and environment information.

context: ContextProxy

Context provides access to information about the current execution environment, headers, and request details.

Key Properties:

  • Headers: Access to HTTP headers from the request
  • Environment: Information about the execution context
  • Request Details: Client and server information

Example usage:

# Access request headers
headers = st.context.headers
user_agent = headers.get("User-Agent", "Unknown")
referer = headers.get("Referer")

# Client information
st.write(f"User Agent: {user_agent}")

# Check for specific headers
if "Authorization" in headers:
    auth_token = headers["Authorization"]
    user = validate_token(auth_token)

Legacy Query Parameter Functions (Deprecated)

These functions are deprecated but still available for backward compatibility.

def experimental_get_query_params():
    """
    Get current query parameters (deprecated).

    Returns:
        dict: Current query parameters

    Note:
        Deprecated in favor of st.query_params
    """

def experimental_set_query_params(**kwargs):
    """
    Set query parameters (deprecated).

    Args:
        **kwargs: Query parameters to set

    Note:
        Deprecated in favor of st.query_params
    """

State Management Patterns

Widget State Synchronization

# Automatic state sync with key parameter
name = st.text_input("Name", key="user_name")
# st.session_state.user_name is automatically updated

# Manual state access
if st.session_state.user_name:
    st.write(f"Hello, {st.session_state.user_name}!")

# Callback with state update
def on_name_change():
    st.session_state.greeting = f"Hello, {st.session_state.user_name}!"

st.text_input("Name", key="user_name", on_change=on_name_change)

Multi-Step Workflows

# Initialize workflow state
if "step" not in st.session_state:
    st.session_state.step = 1
    st.session_state.form_data = {}

# Step navigation
if st.session_state.step == 1:
    name = st.text_input("Enter name")
    if st.button("Next") and name:
        st.session_state.form_data["name"] = name
        st.session_state.step = 2
        st.rerun()

elif st.session_state.step == 2:
    email = st.text_input("Enter email")
    col1, col2 = st.columns(2)
    with col1:
        if st.button("Previous"):
            st.session_state.step = 1
            st.rerun()
    with col2:
        if st.button("Submit") and email:
            st.session_state.form_data["email"] = email
            submit_form(st.session_state.form_data)
            st.success("Form submitted!")

Conditional State Initialization

# Initialize state with default values
defaults = {
    "user_preferences": {"theme": "light", "language": "en"},
    "app_data": {"last_sync": None, "version": "1.0"},
    "ui_state": {"sidebar_expanded": True, "current_tab": 0}
}

for key, value in defaults.items():
    if key not in st.session_state:
        st.session_state[key] = value

# Or with a helper function
def init_state(key, default_value):
    if key not in st.session_state:
        st.session_state[key] = default_value

init_state("counter", 0)
init_state("messages", [])
init_state("user_data", {})

URL-Driven Navigation

# URL-based page routing
def navigate_to(page_name):
    st.query_params["page"] = page_name
    st.rerun()

# Page selector that updates URL
current_page = st.query_params.get("page", "home")

pages = {
    "home": "🏠 Home",
    "data": "📊 Data",
    "settings": "⚙️ Settings"
}

# Create navigation
selected = st.selectbox("Navigate to:",
    options=list(pages.keys()),
    format_func=lambda x: pages[x],
    index=list(pages.keys()).index(current_page) if current_page in pages else 0
)

if selected != current_page:
    navigate_to(selected)

# Display current page
if current_page == "home":
    st.title("Home Page")
elif current_page == "data":
    st.title("Data Page")
elif current_page == "settings":
    st.title("Settings Page")

State Persistence Across Sessions

# Save state to external storage
def save_state():
    state_data = {
        "user_preferences": st.session_state.get("user_preferences", {}),
        "app_settings": st.session_state.get("app_settings", {})
    }
    # Save to file, database, etc.
    save_to_storage(user_id, state_data)

def load_state():
    # Load from file, database, etc.
    state_data = load_from_storage(user_id)
    if state_data:
        st.session_state.update(state_data)

# Initialize with saved state
if "loaded" not in st.session_state:
    load_state()
    st.session_state.loaded = True

# Save state periodically or on changes
if st.button("Save Preferences"):
    save_state()
    st.success("Preferences saved!")

Install with Tessl CLI

npx tessl i tessl/pypi-streamlit

docs

advanced-features.md

caching-performance.md

components-config.md

display-elements.md

index.md

input-widgets.md

layout-containers.md

navigation-pages.md

state-management.md

user-auth.md

tile.json