Radio button switches back to old values after saving and reloading file

Hi there,

In my app the radio buttons show unexpected behavior

When loading settings from a JSON file and changing them with the st.radio it works perfectly for numeric values and text, but when using radio buttons the button moves back to the old value.

Here is my simplified code:

import json
import os

from pathlib import Path

import streamlit as st

settings_folder = "settings"
settings_files = os.listdir(settings_folder)
settings_files.insert(0, '')

settings_names = [Path(s).stem for s in settings_files]

st.markdown("# Test with radio button")
st.sidebar.header("Test with radio button")

option = st.selectbox(
    'Pick one:',
    settings_names, key='selectbox')

st.write('Current selection:', option)

if option:
    with open(f'{settings_folder}/{option}.json') as json_file:
        data = json.load(json_file)
        form = st.form("Settings")
        with st.form("my_form", clear_on_submit=True):
            for d in data:
                name = d
                for e in data[d]:
                    label = e
                    CurrentValue = data[d][e]['CurrentValue']

                    if data[d][e]['DataType'] == "radio":
                        options = json.loads(data[d][e]['Options'])
                        index = options.index(CurrentValue)
                        st.radio(label, options, index=index,
                                 key=label, help=None, horizontal=False)
                    else:
                        pass

            # Every form must have a submit button.
            submitted = st.form_submit_button("Save settings")
            if submitted:
                for val in st.session_state:
                    if (val in data[name]):
                        data[name][val]['CurrentValue'] = st.session_state[val]

                with open(f'{settings_folder}/{name}.json', 'w') as outfile:
                    json.dump(data, outfile, indent=4, sort_keys=False)
                st.json(st.session_state)

else:
    st.warning('Nothing selected')


It needs a subfolder as well with the dummy settings files, working example can be downloaded here:

I am not sure what goes wrong here, I already tried to:

  • Delete the object ‘data’ after writing so I am sure the settings are loaded from disk
  • Add time.sleep() before loading, so the write must have been completed
  • Change clear_on_submit to False, which seems to change the behavior slightly but not fix it
  • Add st.stop() after writing the file
  • Change submitted bool to False

So right now I am pretty much out of ideas, but it is probably something in my end.

Edit:
I just figured out that adding a sleep after writing the file causes the page to already reload.

So I think the question now is how to prevent a page from reloading and wait for all the work to finish?

I just did some more testing. If I write the timestamp from when the file got opened, it always opens earlier than the write is finished. Even when executing the write in a thread, and even when adding a sleep before it opens the JSON file.

Does anyone know why a sleep that is executed in a reloaded page effects the handling of the old page?

Also just noticed that even when deleting the selectbox option and calling st.stop()

del st.session_state.selectbox
st.stop()

it takes two clicks on the submit button before no data is shown.

Small update. It seems that pressing the form Submit button is not guaranteed to finish anything before the next page reload. Pressing it and changing some st.session_state variables don’t show up on the reloaded page.