After experimenting a bit, I realized that the issue was related to how rerun() interacts with the order of code execution. Initially, my code looked like this:
if 'radio_selection' not in st.session_state:
st.session_state.radio_selection = "A" # default value
if st.button("reload", on_click=st.cache_data.clear):
st.write("Cache cleared")
st.rerun()
radio_state = st.radio("Radio", ["A", "B", "C"], index=0)
st.session_state.radio_selection = radio_state
st.write(radio_state)
As I mentioned before, this caused the radio button to visually stay on the selected option (like “C”), but after clicking reload, the displayed value reverted to “A.”
First Attempt:
I thought this was because rerun()
was processed before the radio button selection. So, I moved the reload button to the end of the script:
if 'radio_selection' not in st.session_state:
st.session_state.radio_selection = "A" # default value
radio_state = st.radio("Radio", ["A", "B", "C"], index=0)
st.session_state.radio_selection = radio_state
st.write(radio_state)
if st.button("reload", on_click=st.cache_data.clear):
st.write("Cache cleared")
st.rerun()
This actually prevented the issue. However, it forced me to place the reload button at the bottom, which isn’t flexible in terms of UI layout since the component placement depends on execution order.
Final Solution:
To solve this, I decided to use st.container()
to separate the layout from the execution flow. Here’s the final working code:
class LayoutDesign:
def __init__(self):
self.reload_button = st.container()
self.radio_button = st.container()
self.preview = st.container()
class Controller:
def reload_button(self, container):
if container.button("reload"):
st.write("Cache cleared")
st.cache_data.clear()
st.rerun()
def radio_button(self, container):
radio_state = container.radio("Radio", ["A", "B", "C"], index=0)
st.session_state["radio_selection"] = radio_state
def preview(self, container):
container.write(st.session_state["radio_selection"])
if "radio_selection" not in st.session_state:
st.session_state["radio_selection"] = "A"
layout = LayoutDesign()
controller = Controller()
controller.radio_button(layout.radio_button)
controller.preview(layout.preview)
controller.reload_button(layout.reload_button)
By using st.container()
, I could control the layout freely without worrying about the execution order affecting the UI.