St.text_input: value not updating

Hi,

New to streamlit, this is my issue: I’m trying to provide the user with an interface to annotate some data. For each item the user should give a label and may optionally leave a comment, and they can navigate across the different items with ‘prev’ and ‘next’ buttons. A basic version of the code is here:

import streamlit as st

N=10

choices_values = ['No label', 'YES','NO', 'NA/unclear']
choices_position = { choice:i for i,choice in enumerate(choices_values) }
map_choice_to_value = { 'No label': None, 'YES': 1, 'NO': 0, 'NA/unclear': -1}
map_value_to_choice = { value:key for key, value in map_choice_to_value.items() }

# go to next pair
def next_pair():
    st.session_state.current_index += 1

# go to previous pair
def prev_pair():
    st.session_state.current_index -= 1

# save 
def change_label():
    choice = st.session_state.select_label
    st.session_state.labels[st.session_state.current_index] = map_choice_to_value[choice]

def edit_comment_area():
    st.session_state.comments[st.session_state.current_index] = st.session_state.comment_area



top_text = st.markdown('**Loading data...**')
# initialize state variables
if 'labels' not in st.session_state:
    st.session_state.labels = [None] * N
if 'comments' not in st.session_state:
    st.session_state.comments = [None] * N
if 'current_index' not in st.session_state:
    st.session_state.current_index = 0
n_labels = sum(x is not None for x in st.session_state.labels)
top_text.markdown(f"**Item {st.session_state.current_index+1}/{N}** ({n_labels}/{N} annotated)")


# User input: label choice
current_label = st.session_state.labels[st.session_state.current_index]
st.radio('Are these two reports similar?', 
                    options= choices_values,
                    index = choices_position[map_value_to_choice[current_label]],
                    key = 'select_label',
                    on_change=change_label)

# User input: optional comments
st.text(st.session_state.comments[st.session_state.current_index])
st.text_area('Comment (optional)', 
                key='comment_area',
                value = st.session_state.comments[st.session_state.current_index],
                on_change=edit_comment_area)

# UI: Previous and next buttons to navigate across the pairs
#
prev_button = st.button('Previous', 
                        on_click=prev_pair, 
                        disabled=st.session_state.current_index == 0)
next_button = st.button('Next', 
                        on_click=next_pair,
                        disabled=st.session_state.current_index == N-1)

The labels part work well: when the user changes a label for item X, navigates to other items, then comes back to item X, they will find the last label they selected for X.

However the comments don’t work: when the user enters a comment it is correctly stored in st.session_state.comments and it can be printed by st.write, but even though the value arg in st.text_area is set to the right text, it does not show up in the text area as expected.

I noticed a few things: entering a comment for item X then another comment for the previous or next item and immediately going back makes the comment appear in the text_area for X. However navigating again in other comments makes both disappear, even though st.session_state.comments contains the correct value.

Am I missing something? How do I obtain the expected behaviour?

Debugging info:

  1. running locally
  2. NA
  3. code included in the post
  4. no error
  5. python 3.8.10, streamlit 1.35.0