Write and text_input updating with delay when clicking on widget


I can’t understand why the variables a, b, and st.session_state_idx do not update in the first 3 st.write calls the first time I click on the button. The last write, right at the bottom of this snippet does show the correct values.
If this is the normal behaviour, could you please explain why? I thought the whole script was re-executed every time I interact with a widget.
Also, could you explain what I would need to do to obtain the desired behaviour?
Many thanks!

Steps to reproduce

def get_numbers(step):
    return np.random.randint(0, 10, 20, dtype=int).reshape((-1, 2))

if "idx" not in st.session_state:
    st.session_state.idx = 0

numbers = get_numbers(0)
a, b = numbers[st.session_state.idx]
st.write(f"idx={st.session_state.idx}, a={a}, b={b}")

st.write(f"{a} x {b} = ")
reponse = st.text_input("Reponse")

run = st.button('Submit')

if run:
    st.write(f"idx={st.session_state.idx}, a={a}, b={b}, reponse={reponse}")
    st.session_state.idx += 1
    a, b = numbers[st.session_state.idx]
    st.write(f"idx={st.session_state.idx}, a={a}, b={b}")

Expected behavior:

I expect all 4 write calls to show the same values at all times

Actual behavior:

Only the last write, at the bottom, shows the current value of the variables. All 3 others show the previous values.

Debug info

  • Streamlit version: 1.21.0
  • Python version: 3.8.16
  • Using pip inside a Docker image
  • OS version: Debian 11.6
  • Browser version: Chrome 112.0.5615.137

When you click a button, the page reloads with that button returning True.

All the content on the page before the button is going to reload the same as it did before.

When the script gets to if run:, the content of the conditional is executed. This includes one line of writing out the values unmodified before the increment occurs.

Here’s another thread where someone was asking and I described the run logic for a couple cases.

Now that makes sense. Thanks for explaining.
What widgets trigger a re-run of the entire page? For instance, it seems that text_input don’t.

Basically all widgets trigger a rerun. The purely organizational items like tabs and expanders don’t since they don’t send anything to the backend. Also, when you put widgets inside a form, that prevents them from sending the update to the backend (and rerunning) until the form submit button is clicked.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.