The problem is that you use a key with a randomly generated value. This randomly generated value will (except by random chance) be different every time the script reruns. Streamlit will have no way of providing continuity between reruns. I generally advise to never use random keys because
- you can’t control if something will accidentally be the same by chance when you want it to be different and
- you have to be careful that your randomly generated value goes into
st.session_state
so that it doesn’t change with each rerun before you want it to change.
If you truly need a fresh key every time to force a widget to reset I either have an index that I increment or use a timestamp which is guaranteed to be different each time.
Generally though, you want a widget to be stateful for at least a period of time or for a set of user actions before you reset it, so most often I use an index for dynamically generated widgets where I have complete control over what that index is and when/if I increment or discard it.
I would remove all random generation within your custom class. I would instead pass a key to the class to use to identify that instances widgets. Here is a simplified example of what I mean:
import streamlit as st
if 'results' not in st.session_state:
st.session_state.results = {}
st.session_state.step = 0
class Example():
def __init__(self, options, key):
def save():
st.session_state.results[key] = {
'options': st.session_state[f'{key}_options'],
'slider': st.session_state[f'{key}_slider']
}
st.session_state.step += 1
st.radio('Options', options, key=f'{key}_options')
st.slider('Slider', key=f'{key}_slider')
st.button('Next', on_click=save, key=f'{key}_next')
Example(['a', 'b', 'c'], st.session_state.step)
st.write(st.session_state.results)
And if you want to show them in sequence, you would have a for i in range(st.session_state.step)
loop to show each in succession. In that case, I recommend you also add in a parameter to disable the widgets within a particular instance of a class so that only the newest one is clickable.