Button not disappearing when the page refreshes with long-running function

Hi there:

I’m running a streamlit app locally, using Python 3.11.7 and streamlit 1.42.2.

My problem is that when a page reload triggers a long running process, the button that caused the process to kick-off doesn’t disappear while the long-running process is running. Even worse, it stays active and can be clicked while the progress bar is updating.

Here’s a minimal fully working app that displays the problem

import streamlit as st
import time

print('App-rerun')

if st.session_state.get('btn_run', False):
    progress = st.progress(0)
    for i in range(5):
        progress.progress((i+1)/5)
        time.sleep(1)

    st.write('Done')
else:
    st.write('Lots of text')
    st.write('More text here')
    btn_run = st.button('Run', key='btn_run')

When you click on the button, it remains visible while the progress bar is updating. How can I fix this?

Thanks!

FYI, in case anyone comes upon this thread, I solved this by using a multipage app… Though I’d still love to know if it’s solvable on a single page app!

import streamlit as st
import time

def first_page():
    st.write('Lots of text')
    st.write('More text here')
    st.write('More text here')
    st.write('More text here')
    st.write('More text here')
    st.write('More text here')
    st.write('More text here')
    st.write('More text here')
    st.write('More text here')
    btn_run = st.button('Run')

    if btn_run:
        st.switch_page(p2)

def second_page():
    progress = st.progress(0)
    for i in range(5):
        progress.progress((i+1)/5)
        time.sleep(1)

    st.write('Done')

p1 = st.Page(first_page, title='p1')
p2 = st.Page(second_page, title='p2')

pg = st.navigation([p1, p2], position='hidden')

pg.run()

This comes up a lot with chat layouts and with spinner/progress elements. You can use containers and/or empties to clear the elements. Here’s another thread about it. (Not exactly the same scenario. Let me know if it’s not clear.) Streamlit Spinner and Chat Message odd interaction - #2 by mathcatsand

When Streamlit reruns, it replaces elements one at a time. (The first element rendered in the rerun replaces the first element from the previous one.) During this process all other elements on the page are in a stale state while Streamlit waits to get through the script. Only at the end of the script run will it discard any leftover stale elements.

Containers and empties given you a way to ensure there is not some nth element sitting on your page during a script run, waiting to find out it’s not getting replaced.

Thanks so much for the response! I read the post and tried this myself every imaginable way, but it still doesn’t work. I’ve put st.empty() containers literally everywhere, and I still get the faded button:

import streamlit as st
import time

print('App-rerun')

with st.empty():
    if st.session_state.get('btn_run', False):
        with st.empty(), st.container():
            progress = st.progress(0)
            for i in range(5):
                progress.progress((i+1)/5)
                time.sleep(1)

            st.write('Done')
    else:
        with st.empty(), st.container():
            st.write('Lots of text')
            st.write('More text here')
            btn_run = st.button('Run', key='btn_run')

Thanks again for the help!

I always dislike having to go for the workaround, but sometimes st.empty() needs a little moment to “take” on the front end:

import streamlit as st
import time

print('App-rerun')


if st.session_state.get('btn_run', False):
    with st.empty():
        time.sleep(.1) # A fraction of a second for the empty to "take"
        with st.container():
            progress = st.progress(0)
            for i in range(5):
                progress.progress((i+1)/5)
                time.sleep(1)
            st.write('Done')
else:
    with st.container():
        st.write('Lots of text')
        st.write('More text here')
        btn_run = st.button('Run', key='btn_run')

Genius!!! Thank you! That’s the solution I wanted.

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