`Race condition` when using `experimental_get_query_params` and inputs
Checklist
- [X] I have searched the existing issues for similar issues.
- [X] I added a very descriptive title to this issue.
- [X] I have provided sufficient information below to help reproduce this issue.
Summary
A race case happens when:
- experimental_get_query_params() - This provides KW variables from localhost:8501/?face=details
- Either
optionsis ordered so thatoptions[0]==face and index=0orindex=options.index(face) - Given face="details", calling st.selectbox('Face Name', options, index, key='face') returns face_name.
- Finally, experimental_set_query_params(face=face_name) - This modifies the variable shown in localhost:8501/?face=grid
When the selection changes, the code is reran and the default (line 2) changes, which triggers another refresh. The observable issue is that line 3 will refresh the page and the selection will be lost.
Why is it a race condition? It doesn't happen every time. With nothing to slow the code, it often retains the value. If I add 100-200ms from 1-2 print messages, it fails ~50% of the time.
Issue: The code expects to sync the URL key-value pairs with streamlit inputs. The issue is caused by changing options or index to set the current value after the page reloads.
Recommendation: The input variable index should not be part of the objects state definition. Alternately, provide a way to dynamically set UI values or better control the flow.
My application involves stepping through data that is effectively an infinite graph. I use it for search and recommendation. Since my app is now a collection of demos (datasets) and HTML+CSS interfaces (faces), with variables for clicked item, query, demo, and face. This URL lead interface is important to allow various apps to connect by sending the user around. I also have embedded submit forms. It all ties together with the KW args in the URL defining the initial state.
Reproducible Code Example
def get_variable(params, title='Face', key='face', options=[]):
#params = st.experimental_get_query_params()
face_name = params.get(key,'')
# print(f'\n[get_variable] {key}={face_name}')
face_name = face_name[0] if isinstance(face_name,list) and len(face_name)>0 else face_name
face_idx = 0
# face_idx = dict(zip(options, range(len(options)))).get(face_name, 0)
# options = sorted(options, key=lambda x: -int(x==face_name))
selection = st.sidebar.selectbox(title, options, index=face_idx, key=f'var_{key}')
# print(f'[get_variable] selection={selection}')
return selection
Steps To Reproduce
above
Expected Behavior
No response
Current Behavior
No response
Is this a regression?
- [ ] Yes, this used to work in a previous version.
Debug info
- Streamlit version:
- Python version:
- Operating System:
- Browser:
- Virtual environment:
Additional Information
No response
Are you willing to submit a PR?
- [ ] Yes, I am willing to submit a PR!
Hi @ldmtwo , do you have a minimally reproducible example?
Can you not add a sleep(1) or something to slow the code?
@willhuang1997 I also encountered this problem as well, below is the code and the gif illustrating the error. Please help us fix it to make the function more robust, really appreciate you guys' effort.
import streamlit as st
selected = st.experimental_get_query_params().get("test", ["1"])[0]
data = ["1", "2", "3", "4", "5"]
selected = st.selectbox("Test", data, index=data.index(selected))
st.experimental_set_query_params(test=selected)

This is a very annoying bug for me too :(
If this issue affects you, please react with a 👍 (thumbs up emoji) to the initial post.
Your feedback helps us prioritize which bugs to investigate and address first.