Streamlit application is cleared after change selection of select-box

Hello everyone! I faced with problem of rerendering application page after change selection of select-box. Could someone help please?

Here is my code:

def main():
    uploaded_file = st.file_uploader("Choose a file")
    if uploaded_file is not None:
        bytes_data = uploaded_file.getvalue()
        file_size = len(bytes_data)
        file_name = uploaded_file.name

        if st.button('Process file'):
            if bytes_data:
                file_path = os.path.join(CACHE, file_name)
                with open(file_path, 'wb+') as f:
                    f.write(bytes_data)

            with st.spinner('Wait for it...'):
                start = timeit.default_timer()
                st.info('Transcribing...')
                meeting_json, duration = assembly_recognition.transcribe_meeting(
                    file_path)
                stop = timeit.default_timer()
                os.remove(file_path)

                # Decompose meeting:
                # Summary, Tasks, Reminders, plans, etc
                st.info('Decomposing...')
                meeting_json = decomposition.decompose(meeting_json)

                with open(os.path.join(DB, f'{file_name}.json'), 'w+', encoding='utf-8') as f:
                    json.dump(meeting_json, f, ensure_ascii=False)

            st.info(f"Elapsed time: {stop - start}")
            st.info(f"File size: {file_size} bytes")
            st.info(f"Duration: {duration}")
            st.info(
                f"Speed: {duration / (stop - start)} seconds video per real second")
            st.info(f"Speed: {file_size / (stop - start)} Bs")
            st.balloons()

            # some streamlit elements here
            full_markdown = streamlit_followup_builder.build_followup(
                meeting_json)

            download_followup(full_markdown, meeting_json)


def download_followup(full_markdown, meeting_json):
    controler = st.container()
    filename = datetime.now().strftime("followup_%H_%M_%S")
    option = controler.selectbox(
        'How would you like to download your followup?',
        ['Markdown', 'JSON', 'PDF'])

    if option == 'Markdown':
        controler.download_button(
            label="Download md",
            data=full_markdown,
            file_name=filename + '.md',
            mime='text/csv')
    elif option == 'JSON':
        controler.download_button(
            label="Download json",
            data=meeting_json,
            file_name=filename + '.json',
            mime='json')
    elif option == 'PDF':
        html_text = markdown(full_markdown, output_format='html4')
        pdfkit.from_string(html_text, filename + '.pdf')
        with open(filename + '.pdf', "rb") as pdf_file:
            PDFbyte = pdf_file.read()
        controler.download_button(
            label="Download pdf",
            data=PDFbyte,
            file_name=filename + '.pdf',
            mime='application/octet-stream')

Hello, @Feodoros!

The reason this happens is because the st.button doesn’t keep its state when the app gets rerun. So, when you change the selectbox, the app gets rerun, and the button is no longer “clicked”. One way to work around this is to switch out the button for a checkbox, and then your code should work fine. But, you can also use st.session_state to save the fact that the button was ever clicked.

if "clicked" not in st.session_state:
    st.session_state.clicked = False
if st.button("Process file") or st.session_state["clicked"]:
    st.session_state["clicked"] = True
    ...

Also, when you change the selectbox, all of the functions inside the if st.button... will be rerun, so if any of them are slow, or intensive to run, you might want to use st.experimental_memo to cache them so they don’t need to be rerun every time.

1 Like

Yeah, thanks a lot! I did it with session_state and it works great! Streamlit is awesome!

1 Like