Control state of `st.expander`

Thanks! That helps to clarify things. I tried that approach, and it kind of works. Sometimes it works after one click, sometimes I need to click 5+ (and thatโ€™s not with spamming clicks) times for the expander to close. The inconsistency is a bit confusing.

import streamlit as st
import time

st.write("The button now only intermittently works. Sometimes after one click. Sometimes after multiple clicks.")
if "expander_state" not in st.session_state:
    st.session_state["expander_state"] = False

def toggle_closed():
    st.session_state["expander_state"] = True
    #open first, then force rerun and closing at the end of script

st.button("do misc. then close expander",on_click=toggle_closed)

with st.expander("test expander",expanded = st.session_state["expander_state"]):
    st.write("expander is open")

if st.session_state["expander_state"] == True:
    st.session_state["expander_state"] = False
    # time.sleep(0.05) <-- For some reason this fixes the problem!? 0.05 was as short as I could push it. When I went down to 0.01 sometimes the inconsistent button behavior would show up again.
    st.experimental_rerun()

Another question: how does streamlit know how to connect one instance of an expander (or any widget) to itself between runs? Is it just by the order in which expanders are defined? E.g. the second expander will always check against how the second expander was defined in a previous run. For a regular widget I assumed that it might be the session_state key, but expanders, as containers, donโ€™t have keys. Thanks!

EDIT: I found that sleeping for a short bit before the experimental_rerun() seemed to fix things. However, I had to sleep for > 0.05s for the behavior to be consistent.