User interaction needed to run twice the same button with success

Summary

User interaction needed to run twice the same button with success.

Steps to reproduce

Code snippet:

import streamlit as st
import requests
import json
from urllib.parse import quote


st.title('Hello world!')

def block(qid, key):
    req = requests.get(f"https://API TEST/gettest?id={str(qid)}")
    st.text_area(json.loads(req.text)['question']['0']
                 , value=json.loads(req.text)['answer']['0']
                 , height=200
                 , key='textblock'+key
                 , placeholder='placeholder here'
                 , disabled=False
                 , label_visibility='visible'
                 )
    bt = st.button('Send!')
    if bt:
        st.write('Sent.')
        update_value(qid, st.session_state['textblock'+key])
        # st.experimental_rerun()

    
def update_value(qid, value):
    requests.post(f"https://API TEST/settest?id={str(qid)}&value={quote(str(value))}")
    st.write(value)

block(qid=1, key='001')

In order to reproduce, an API is necessary.

Expected behavior:

I am retrieving a value from a database through an API. The table is simple, 3 columns:

  • id
  • question
  • answer

When it loads gets the query and the answer and shows a text box with those values. The user should be able to edit the answer and click send button to update the values in the database.

Actual behavior:

The first time I run it, it actually works. But if I then change the text box again and click in send again, it wont update. In fact it will change the value of the box to the previous version.

I know it has to do something with usert not interacting after the first “send” action and the second. If the users interacts elsewhere and then clicks “send” for a second time, it works.

Also you can uncomment the experimental_rerun line an it will work because it forces to refresh.
Or, If not using the requests function (comment the request.post line in update_values function), it will work as expected as well.

So I know more or less where is the error but cannot figure out how to fix or workaround it.

Debug info

  • Streamlit version: 1.26.
  • Python version: 3.10
  • Using Conda? PipEnv? PyEnv? Pex? conda
  • OS version: tried several
  • Browser version: Chrome 116

Requirements file

Using Conda? PipEnv? PyEnv? Pex? Share the contents of your requirements file here.
Not sure what a requirements file is? Check out this doc and add a requirements file to your app.

Here’s a modified version that uses st.session_state in the place of an API

import streamlit as st


st.title("Hello world!")

if "api" not in st.session_state:
    st.session_state["api"] = {
        "1": {
            "question": "What is your name?",
            "answer": "My name is ...",
        },
        "2": {
            "question": "What is your age?",
            "answer": "My age is ...",
        },
    }


def get_from_api(qid):
    return st.session_state["api"][str(qid)]


def post_to_api(qid, answer):
    st.session_state["api"][str(qid)]["answer"] = answer


def block(qid):
    resp = get_from_api(qid)
    answer = st.text_area(
        resp["question"],
        value=resp["answer"],
        height=200,
        placeholder="placeholder here",
        disabled=False,
        label_visibility="visible",
    )
    bt = st.button("Send!", key=qid)
    if bt:
        st.write("Sent.")
        update_value(qid, answer)


def update_value(qid, answer):
    post_to_api(qid, answer)
    st.write(answer)


block(qid=1)

block(qid=2)

st.write("Database state:")
st.session_state["api"]
1 Like

Thanks for the code for reproducibility! But the issue is still there, I get the same behaviour that I explained… Any ideas how to fix?

Do you see that behavior if you write to session_state instead of a database like my code does?

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