St.tabs - How to prevent rerun and jumping back to Tab 1?

Hello,

I currently have the following problem with the tabs. I added two tabs on my page and in both select boxes as an example. If I change the select box in Tab 2, the program jumps back to Tab 1.

I know I can use a form with a button. However, as soon as the button is pressed and a function is executed in the background, the program also jumps back to Tab 1.

I don’t think this can be intentional. How can I stop this behavior? Is there a way to read and cache the index of the tabs?

Here is some example code:

         tab1, tab2 = st.tabs(option_menu_database)

         with tab1:                                                   
            st.header("View")
            with st.form("database_view"):
               db_tables = pd.DataFrame(database_tables())
               selected_table = st.selectbox("Tables",db_tables)

               if st.form_submit_button("Load tables"):

                  db_table = pd.DataFrame(database_get_table(selected_table))
                  st.write(db_table)

         with tab2:                                                     
            st.subheader("Edit")
            with st.form("database_edit"):
               select_choice = st.selectbox("What do you want to edit?",("Database","Table"))
               if st.form_submit_button("Load"):
                  db_tables = pd.DataFrame(database_get_table(select_choice))
                  selected_table = st.selectbox("Tables",db_tables)
            st.markdown("---")

I hope you can help me.

Thanks in advance!

2 Likes

Ok, sorry guys. I guess I missed this entry in the documentation:

Warning

All the content of every tab is always sent to and rendered on the frontend. Conditional rendering is currently not supported.

Really, i love Streamlit. But this whole rerun thing is really…

Hope you get rid of this behaviour in the future or make tabs accessable for session states etc. :slight_smile:

Check out the navbar component here

I had the same problem as you, and this solved it for me

1 Like

see the same issue. hope can prevent the tab jump

I have the same issue, I tried the hydralit_components, I found it re-runs when switch tabs, but streamlit tab doesn’t rerun. Not sure which one I prefer since I like ‘switch tab and no rerun’ + ‘tabs don’t jump back to tab1’

My tabs don’t jump back to the first tab.

same issue, would be great if tab jump be prevented

Is there any plan to support fixes for this? Currently seeking to use tabs in Streamlit apps hosted in Snowpark, and it appears to follow little rhyme/reason about re-rendering and jumping back to the first tab.

One might think this is due to session_state data being modified across tabs, but alas, no - completely decoupled session_state variables for tab3, compared to tab1 and tab2 (who share some session state). Absolutely no jumping back from tab2 to tab1, when UI elements are interacted with. But anything that causes a cleaning of UI widgets in tab3 forces tab1 to regain focus.

It would be helpful to know if elegant tab behavior will be supported without use of custom components (note the Streamlit-in-Snowpark reference), or if we should seek alternative UI/UX options.

Thoughts?

Same here. This is borderline unusable this way.

Same here. St.tabs jumping to first tab is a very stupid bug. Also re-rendering ever time you switch between component inputs is not ideal.

+1 here. I saw another issue which advised declaring the tabs as the first streamlit call to work around this but (a) we want our tab bar below our dashboard title and (b) I believe the fact we are importing functions which run st commands is interfering too.

Is there an issue in github for this problem given how many times it has come up in discussions here?

+1

For now, I used st.radio with some CSS hack to make it look like a tab. My use case was slightly different; I want to only render content of tabs that is selected.

def tabs(default_tabs = [], default_active_tab=0):
        if not default_tabs:
            return None
        active_tab = st.radio("", default_tabs, index=default_active_tab)
        child = default_tabs.index(active_tab)+1
        st.markdown("""  
            <style type="text/css">
            div[role=radiogroup] {
                border-bottom: 2px solid rgba(49, 51, 63, 0.1);
            }
            div[role=radiogroup] > label > div:first-of-type {
               display: none
            }
            div[role=radiogroup] {
                flex-direction: unset
            }
            div[role=radiogroup] label {
                padding-bottom: 0.5em;
                border-radius: 0;
                position: relative;
                top: 3px;
            }
            div[role=radiogroup] label .st-fc {
                padding-left: 0;
            }
            div[role=radiogroup] label:hover p {
                color: red;
            }
            div[role=radiogroup] label:nth-child(""" + str(child) + """) {    
                border-bottom: 2px solid rgb(255, 75, 75);
            }     
            div[role=radiogroup] label:nth-child(""" + str(child) + """) p {    
                color: rgb(255, 75, 75);
                padding-right: 0;
            }            
            </style>
        """,unsafe_allow_html=True)        
        return active_tab

active_tab = tabs(["Tab 1", "Tab 2", "Tab 3"])
st.write(active_tab)

2 Likes