Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

In selectbox, if options chage from None to not, the defalut value rendered is still None. #10093

Open
3 of 4 tasks
vivianyang11 opened this issue Dec 30, 2024 · 14 comments
Open
3 of 4 tasks
Labels
feature:st.selectbox priority:P3 status:confirmed Bug has been confirmed by the Streamlit team type:bug Something isn't working

Comments

@vivianyang11
Copy link

Checklist

  • I have searched the existing issues for similar issues.
  • I added a very descriptive title to this issue.
  • I have provided sufficient information below to help reproduce this issue.

Summary

image
in the selectbox code, line 313-314, it shows that if last time, the selected item is None, change the index to None. This will cause a problem that if options chage from None to not, the defalut value rendered is still None.

Reproducible Code Example

No response

Steps To Reproduce

No response

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:

Additional Information

No response

@vivianyang11 vivianyang11 added status:needs-triage Has not been triaged by the Streamlit team type:bug Something isn't working labels Dec 30, 2024
Copy link

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.

Visits

@sfc-gh-dmatthews
Copy link
Collaborator

Can you provide a code snippet and steps to reproduce the problem?

Since the value in Session State and the output of the widget is the option value and not the index, I can't generate an error from this. I tried a simple selectbox with a None option included. When choosing between None, some other option, or nothing selected, the widget always had the correct value and showed placeholder text when nothing was selected.

import streamlit as st

a = st.selectbox("A", [1, 2, None], index=None, key="key")
st.session_state.key
a

@vivianyang11
Copy link
Author

Can you provide a code snippet and steps to reproduce the problem?

Since the value in Session State and the output of the widget is the option value and not the index, I can't generate an error from this. I tried a simple selectbox with a None option included. When choosing between None, some other option, or nothing selected, the widget always had the correct value and showed placeholder text when nothing was selected.

import streamlit as st

a = st.selectbox("A", [1, 2, None], index=None, key="key")
st.session_state.key
a

here is the code:

import streamlit as st

project = st.selectbox("Select the project", options=[1, 2], key="project_selection")

if project == 1:
    dataset_option = []
elif project == 2:
    dataset_option = ["dataset1", "dataset2"]

dataset = st.selectbox("Select the dataset", options=dataset_option, key="dataset_selection", index=0 if len(dataset_option) > 0 else None)

if dataset is None:
    st.error("No datasets available.")

with this kind of situation, index will never work after project from 1 to 2.

The expected rendering should be that when 'project2' is selected, the dataset selectbox should default to 'dataset1', because index=0 if len(dataset_option) > 0 else None.

However, if you run the code, you will find that with project changes, dataset is always defalut to be None.

@vivianyang11
Copy link
Author

this problem will happen in v1.40.0 and v1.41.0. but in 1.33.0, it works as expected

@sfc-gh-dmatthews
Copy link
Collaborator

That makes sense. The ability to set the initial value to None was added in 1.34.0. I was able to reproduce the issue with your code. I added another option to force a clearing of the key from Session State, as well:

import streamlit as st

st.write(st.session_state)
st.button("Rerun")

project = st.selectbox("Select the project", options=[1, 2, 3], key="project_selection")

if project == 1:
    dataset_option = []
elif project == 2:
    dataset_option = ["dataset1", "dataset2"]

if project != 3:
    dataset = st.selectbox("Select the dataset", options=dataset_option, key="dataset_selection", index=0 if len(dataset_option) > 0 else None)
    if dataset is None:
        st.error("No datasets available.")

st.write(st.session_state)
  1. Load the page
  2. Select project 2
  3. Observe the default value is not "dataset1" as expected.
  4. Select project 3
  5. Click rerun to confirm the dataset key is cleared from Session State.
  6. Select project 2
  7. Observe the default value is "dataset1" as expected.

@vivianyang11
Copy link
Author

That makes sense. The ability to set the initial value to None was added in 1.34.0. I was able to reproduce the issue with your code. I added another option to force a clearing of the key from Session State, as well:

import streamlit as st

st.write(st.session_state)
st.button("Rerun")

project = st.selectbox("Select the project", options=[1, 2, 3], key="project_selection")

if project == 1:
    dataset_option = []
elif project == 2:
    dataset_option = ["dataset1", "dataset2"]

if project != 3:
    dataset = st.selectbox("Select the dataset", options=dataset_option, key="dataset_selection", index=0 if len(dataset_option) > 0 else None)
    if dataset is None:
        st.error("No datasets available.")

st.write(st.session_state)
  1. Load the page
  2. Select project 2
  3. Observe the default value is not "dataset1" as expected.
  4. Select project 3
  5. Click rerun to confirm the dataset key is cleared from Session State.
  6. Select project 2
  7. Observe the default value is "dataset1" as expected.

And as I posted, Are these two lines(313-314) of code necessary? What issues would arise if they were commented out? Adding an extra button to clear st.session_state is a supplementary and redundant operation. I don't think this is a perfect solution
image

@sfc-gh-dmatthews
Copy link
Collaborator

Apologies for the confusion. I wasn't suggesting a solution; I was trying to assist the devs for when they get back from holiday break so they can jump right to marking this as confirmed and prioritizing the fix. 🙂

@vivianyang11
Copy link
Author

这很有道理。在 1.34.0 中添加了设置初始值的功能None。我能够使用您的代码重现该问题。我还添加了另一个选项来强制从会话状态中清除密钥:

import streamlit as st

st.write(st.session_state)
st.button("Rerun")

project = st.selectbox("Select the project", options=[1, 2, 3], key="project_selection")

if project == 1:
    dataset_option = []
elif project == 2:
    dataset_option = ["dataset1", "dataset2"]

if project != 3:
    dataset = st.selectbox("Select the dataset", options=dataset_option, key="dataset_selection", index=0 if len(dataset_option) > 0 else None)
    if dataset is None:
        st.error("No datasets available.")

st.write(st.session_state)
  1. 加载页面
  2. 选择项目 2
  3. 观察默认值不是预期的“dataset1”。
  4. 选择项目 3
  5. 单击“重新运行”以确认数据集键已从会话状态中清除。
  6. 选择项目 2
  7. 观察默认值**是否**如预期的那样为“dataset1”。

That makes sense. The ability to set the initial value to None was added in 1.34.0. I was able to reproduce the issue with your code. I added another option to force a clearing of the key from Session State, as well:

import streamlit as st

st.write(st.session_state)
st.button("Rerun")

project = st.selectbox("Select the project", options=[1, 2, 3], key="project_selection")

if project == 1:
    dataset_option = []
elif project == 2:
    dataset_option = ["dataset1", "dataset2"]

if project != 3:
    dataset = st.selectbox("Select the dataset", options=dataset_option, key="dataset_selection", index=0 if len(dataset_option) > 0 else None)
    if dataset is None:
        st.error("No datasets available.")

st.write(st.session_state)
  1. Load the page
  2. Select project 2
  3. Observe the default value is not "dataset1" as expected.
  4. Select project 3
  5. Click rerun to confirm the dataset key is cleared from Session State.
  6. Select project 2
  7. Observe the default value is "dataset1" as expected.

And as I posted, Are these two lines(313-314) of code necessary? What issues would arise if they were commented out? Adding an extra button to clear st.session_state is a supplementary and redundant operation. I don't think this is a perfect solution image

That makes sense. The ability to set the initial value to None was added in 1.34.0. I was able to reproduce the issue with your code. I added another option to force a clearing of the key from Session State, as well:

import streamlit as st

st.write(st.session_state)
st.button("Rerun")

project = st.selectbox("Select the project", options=[1, 2, 3], key="project_selection")

if project == 1:
    dataset_option = []
elif project == 2:
    dataset_option = ["dataset1", "dataset2"]

if project != 3:
    dataset = st.selectbox("Select the dataset", options=dataset_option, key="dataset_selection", index=0 if len(dataset_option) > 0 else None)
    if dataset is None:
        st.error("No datasets available.")

st.write(st.session_state)
  1. Load the page
  2. Select project 2
  3. Observe the default value is not "dataset1" as expected.
  4. Select project 3
  5. Click rerun to confirm the dataset key is cleared from Session State.
  6. Select project 2
  7. Observe the default value is "dataset1" as expected.

btw, as the way you said "Click rerun button" will not show the "dataset1" as expected, because, a "st.rerun" is needed? I think

@sfc-gh-dmatthews
Copy link
Collaborator

If you want a workaround for this until it's fixed, clearing the key from Session State would work:

import streamlit as st

def clear_key():
    del st.session_state.dataset_selection

project = st.selectbox("Select the project", options=[1, 2], key="project_selection", on_change=clear_key)

if project == 1:
    dataset_option = []
elif project == 2:
    dataset_option = ["dataset1", "dataset2"]

dataset = st.selectbox("Select the dataset", options=dataset_option, key="dataset_selection", index=0 if len(dataset_option) > 0 else None)
if dataset is None:
    st.error("No datasets available.")

@sfc-gh-dmatthews
Copy link
Collaborator

sfc-gh-dmatthews commented Dec 31, 2024

btw, as the way you said "Click rerun button" will not show the "dataset1" as expected, because, a "st.rerun" is needed? I think

The st.rerun isn't technically needed. The key is cleared when the script run finishes after selecting 3. You just can't see that the key was cleared because Session State is displayed during the script run. I just added that to be complete in demonstrating the different pieces that show the bug (or not).

@vivianyang11
Copy link
Author

如果您想要一个解决方法直到问题解决,那么从会话状态中清除密钥会起作用:

import streamlit as st

def clear_key():
    del st.session_state.dataset_selection

project = st.selectbox("Select the project", options=[1, 2], key="project_selection", on_change=clear_key)

if project == 1:
    dataset_option = []
elif project == 2:
    dataset_option = ["dataset1", "dataset2"]

dataset = st.selectbox("Select the dataset", options=dataset_option, key="dataset_selection", index=0 if len(dataset_option) > 0 else None)
if dataset is None:
    st.error("No datasets available.")

I get that. And will this be

If you want a workaround for this until it's fixed, clearing the key from Session State would work:

import streamlit as st

def clear_key():
    del st.session_state.dataset_selection

project = st.selectbox("Select the project", options=[1, 2], key="project_selection", on_change=clear_key)

if project == 1:
    dataset_option = []
elif project == 2:
    dataset_option = ["dataset1", "dataset2"]

dataset = st.selectbox("Select the dataset", options=dataset_option, key="dataset_selection", index=0 if len(dataset_option) > 0 else None)
if dataset is None:
    st.error("No datasets available.")

Will this be fixed in the feature? 😂

@sfc-gh-dmatthews
Copy link
Collaborator

sfc-gh-dmatthews commented Dec 31, 2024

I'll defer to the devs when they get back from holiday break. 😅 My guess is: probably.

It is the case in general that if you have a widget with key="A" on one script run (with some value assigned to it), and you have a different widget with key="A" on the next rerun (such as by changing one of the defining parameters of that widget), then Streamlit should delete the key and reinitialize it with the new widget's default value. So there might be some logic on a deeper level that needs fixing. Since the value of a previous widget is bleeding into a new one, there might be an issue a few lines up with computing and registering the widget ID instead...

@sfc-gh-lwilby sfc-gh-lwilby added status:confirmed Bug has been confirmed by the Streamlit team priority:P3 feature:st.selectbox and removed status:needs-triage Has not been triaged by the Streamlit team labels Jan 2, 2025
@sfc-gh-lwilby
Copy link
Collaborator

Hi @vivianyang11 ,

Thank you for filing this issue! I've confirmed it and triaged the issue for fixing.

Thank you @sfc-gh-dmatthews for providing a workaround.

Laura

@sfc-gh-dmatthews
Copy link
Collaborator

@sfc-gh-lwilby I noticed it also happens with st.radio, too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature:st.selectbox priority:P3 status:confirmed Bug has been confirmed by the Streamlit team type:bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants