Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Experimental ventures into type-safe global Streamlit state and out-of-order layouts
from abc import ABC
import streamlit as st
class _TypedState:
"""
Values should be set here to appear in auto-complete. Otherwise assume they don't exist in the global state
"""
def __init__(self) -> None:
self.some_value: int = 0
class Component(ABC):
"""
Base component that takes care of state reference
"""
# Make a typed state object
st.session_state["state"] = _TypedState()
# Make it available to all child classes without needing super().__init__()
state: _TypedState = st.session_state["state"]
class TextBox(Component):
"""
Inherit from parent component and initialize a reference to Streamlit's state, but typed
"""
def __init__(self, name: str) -> None:
st.text(f"Shared state for {name} is: {self.state.some_value}")
class Slider(Component):
"""
Changes state for all components here
"""
def __init__(self) -> None:
self.state.some_value = st.slider(
min_value=0, max_value=100, value=self.state.some_value, label="change state value (set 0 to disable text)"
)
class Layout:
"""
Layout and no other concerns
"""
text1 = st.empty()
text2 = st.empty()
text3 = st.empty()
# Will appear last because of layout
slider = st.empty()
class App(Component):
"""
Tie everything together
"""
def __init__(self) -> None:
layout = Layout()
# Must be first to control state flow "downwards"
with layout.slider:
Slider()
if self.state.some_value == 0:
return
with layout.text1:
TextBox("text 1")
with layout.text2:
TextBox("text 2")
with layout.text3:
TextBox("text 3")
if __name__ == "__main__":
App()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment