Session state/ button interaction yields unexpected order

I want my button to toggle what it says depending on the session state, just like how a play button turns into pause after being clicked and back into play after being clicked again.

Here is the bare reproduction code I wrote to do so. It’s easiest if you just try and run the code because the behaviour is hard to explain.

import streamlit as st

# initialize recording_data as true
if "recording_data" not in st.session_state:
    st.session_state.recording_data = True

toggle_text = "Stop" if st.session_state.recording_data else "Start"
if st.sidebar.button(toggle_text):
    # flip recording_data
    st.session_state.recording_data = not st.session_state.recording_data
    
st.write(st.session_state)

Hitting the button switches recording_data, and hitting the button should also rerun the script, so I expect that since recording_data has been flipped, the text will also change.

Instead, the text changes every second time the button is pressed.

Printing out the session state is a bit revealing:

I expect two states:

  1. Text is “Start”, st.session_state.recording_data = False
  2. Text is “Stop”, st.session_state.recording_data = True

But there are actually 4 states, in this order:

  1. Text is “Start”, st.session_state.recording_data = False
  2. Text is “Start”, st.session_state.recording_data = True
  3. Text is “Stop”, st.session_state.recording_data = True
  4. Text is “Stop”, st.session_state.recording_data = False

It seems to me like code in the button block is run after the site is reloaded, which is maybe a feature, not a bug, but is there a way to do what I want?