How to prevent the reloading of the whole page when I let the user to perform an action

I just see the definition of a function. How do you call it? How does the input for LLok change? How is choice defined?

LLok can change, it is the checkbox options. Here I show how the function is called:

Buttons do not remember their state. They will return True on the page load resulting from their click, then go back to False as soon as the user interacts with anything else. Since you put plotLL(LLok) inside the conditional coming direct from a button, it will go away as soon as the user clicks on anything else.

A couple of recommendations:

I’m not sure how big your csv file is, but as a good habit, I recommend caching your def list_events(csv_file) function so you aren’t actually re-reading the data each time.

@st.experimental_memo
def list_events(csv_file):
    evl=pd.read_csv(csv_file, sep",",engine='python')
    return evl.columns[1:].values.tolist()

evl_list = list_events('test.csv')

There are several different solutions and ways to restructure this. You could put your inputs into a form so that clicking them won’t rerun the page, but you’d still have the same problem if there are other things on the page a user could interact with.

As a minimal alteration try taking that image information and storing it in session state instead.

At the top of your app, initialize a place in session state to store your image:

if 'image' not in st.session_state:
    st.session_state.image = None

In your plotLL function, save the image to session state instead of displaying directly within the function. Change the line st.image(image) to

st.session_state.image = image

The at the bottom below the Calculate, make it display the image after executing the function and pulled from session state (which will only get updated with a new click of the Calculate button.

if st.button('Calculate'):
    plotLL(LLok)

if st.session_state.image is not None:
    st.image(st.session_state.image)
1 Like

Thank you very much for the help and recommendations.

1 Like

They do if you use streamlit extras! :smiley: https://extras.streamlit.app/Stateful%20Button

1 Like

This is true!

I have continued with my App but I have a new problem, I don’t want the image displayed with the plotLLL function to disappear from the screen when I simply select an option from the checkbox or selectbox, because before I click on the calculate button, the image disappears.

#Libraries

from time import time
from PIL import Image
import matplotlib.pyplot as plt
import plotly.figure_factory as ff
import streamlit as st
from astropy import constants as const
from H0live import *

if 'image' not in st.session_state:
    st.session_state.image = None



###########################################
title= 'Latest Standard Siren Measurement'
st.set_page_config(page_title=r'$H_Website$', 
                               initial_sidebar_state= 'expanded',layout="centered")
sb = st.sidebar



#add LOGO.
c1, c2 = st.columns([3, 6])

c1.image('https://yt3.ggpht.com/dsz-32urUxdYKd8a6A2cnmOAo7zCXBtKFXGm_eRjRdYFkqc3IWnKhpAkjY62ATQCLVqLyH7POQ=s900-c-k-c0x00ffffff-no-rj')

st.title(title)
@st.experimental_memo 
def list_events(csv_file):
    ev1=pd.read_csv(csv_file,sep=",",engine='python')
    return ev1.columns[1:].values.tolist()


evl_list = list_events('test.csv')
#Menu. Separate events from counterparties
ev1_list=list_events('test.csv')

LLo=[]
for i in range(len(ev1_list)):
    if ev1_list[i][0:8] not in LLo:
        LLo.append(ev1_list[i][0:8])
ctp=[]
for i in range(len(ev1_list)):
    if ev1_list[i][9:12] not in ctp:
        ctp.append(ev1_list[i][9:12])
LLok=[]

sb.header("Events")
for i in range(len(LLo)):
    default_value=LLo[0]
    LLok.append(st.sidebar.checkbox(LLo[i],value=default_value))
    

stb_list=[]


for i in range(len(LLok)):
    ctp_list=[]
    for x in range(len(ctp)):
        if LLo[i]+"_"+ctp[x] in ev1_list:
            ctp_list.append(ctp[x])
    stb_list.append(st.selectbox("Counterpart "+str(i+1),ctp_list,key=str(i+1),label_visibility="collapsed"))

#To select the desired prior
prior_list=['uniform', 'log']
choice = st.selectbox("Priors",prior_list) 



#H0live action

choice_list1=[]
for i in range(len(LLok)):
    if LLok[i]==True:
        choice_list1.append(LLo[i]+"_"+stb_list[i])



def plotLL(choice_list1):
    if choice== 'uniform' or 'log':
        h0c= H0live(choice_list1, choice)



if st.button("Calculate")==True :
    plotLL(choice_list1)

if st.session_state.image is not None:
    st.image(st.session_state.image)
    
    




#For the graph 



# Sidebar
sb.header("Related information")
sb.markdown("About gravitational wave events: [GraceDB](https://gracedb.ligo.org/api/events/)")
sb.markdown(
    "What is LIGO?: [LIGO](https://www.ligo.org/about.php)")

sb.markdown(
    "How can GW be used to estimate H0? : [Measuring the Expansion of the Universe with Gravitational Waves](https://www.ligo.org/science/Publication-GW170817Hubble/)")

This is what it looks like after clicking the calculate button.


And this is what it looks like when I simply remove an option from the checkbox:

Dear all,

I’ve a page that is structured like this

There are more or less shown 600+ couples of rows that are similar. For a certain condition (depending on the values of the rows) I’m creating a radio button for some couples. I’m ending up with more or less 400 radio buttons. Apart of the fact that the loading of the page is very slow, but every time I click the radio button of a certain couple streamlit reloads the entire page (note that the radio button doesn’t influence the page, so it’s reloading exactly the same page) and it takes ~1 minutes for every radio button and this makes this page unuasble for a user…
Any suggest on how to avoid this? Code snippet here:

Is there a way maybe to cache only the st.write at line 212? This would avoid 80% of the useless reloading of the page. Thanks for helping :slight_smile:

Lorenzo

1 Like

Hello! I need some help. I have built a multipage app on streamlit. All the pages load fast except for the homepage. After I have gone to the other pages, I’ve noticed that the homepage reloads entirely when I return to it. Any idea how to fix this? My homepage only has one button which says “logout”

This is really expected behavior from streamlit , when user changes selection on the app ,it triggers re-run . Use st.cache_data for better experience :balloon:

Hi @lollovela,

Hope that you found the solution for your issue. In case that you did not here is some proposal:
As I understood reason why your radio button is takes to much to load is due to data from df (dataframe) that is above your radio buttons. And the second df is also above the second group of radio buttons. So, the time to load those data for df is too long so it also maybe took time to load your button. You could init your df at the place you init it, but to load data at the bottom of the code, so everything else is already init.
Hope that helps!

DusanP

Hello all, new first post. I think I found a way around this myself working on an app for my company.

Below is a deliberate long running process, 5 seconds :smiley: that’s executed as part of a page load when you click a button, this also sets a state meaning once the process is done the state of the page is established and all interaction with the website won’t need to do that again.

This works with the exception of a F5 to refresh the page.

My loaded process currently take ~ 480 seconds, I only want this to occur once for each user session that hits our websites. Hopefully I can reduce this…But this certainly lets us move forward knowing there is a load timer, I just added a load timer for any new user that logs into the website.

import streamlit as st # Bring in streamlit for UI/app interface
import time

def longproc():
    for x in range(5):
        time.sleep(1)
        x = x +1

peace = st.empty()

if 'key' not in st.session_state:
    with peace:
        if(st.button("Set Key")):
            longproc()
            st.session_state['key'] = 'value'


if 'key' in st.session_state:
    peace.empty()
    st.write(st.session_state.key)
    if(st.button("Set New")):
        st.write("new")        

Refreshing the page stars a new session. If you want state persist across sessions, use caching.

I think Streamlit is Awesome, but it needs some features in order to fix this too much rendering and execution bottle necks problem (The caching is a temporal solution I think, there are a lot of objects the caching do not fit well).

  • A setup function (only runs first time)
  • Rerun widgets calculating its dependency, like modern web apps, this means only re runs the widgets with has a change, that affects its rendering directly or indirectly.
  • Web view components, and more customizable Javascript or Python API for custom components, no developing in Angular or React, in order to give more control to the python users.
  • Or avoiding some widgets to not update its content, only skip in case of some pre calback function bool given by the user.
  • Cookies User session caching, I mean to reload the session thread associated with browser data, and reconnect to the corresponding thread and memory session data (sure you have to close multiple tabs open it if you activate)
  • Global lock to keep some big processed at a first startup, no first user connection, and keep some processed data, stored in memory or disk.

Maybe a good approach is to program the interface or views, and in other files or the same, the behaviours or interactions between every widgets.

And I know, its not easy, but its needed to have a robust and useful modern web app, I think.

3 Likes

Although I am not very familiar with how to implement it, I support change

Perfect thank you! I’ve been flat out with other work, but tested the @st.cache_data and that has prevented the F5 issue.

import streamlit as st # Bring in streamlit for UI/app interface
import time

@st.cache_data
def longproc():
    for x in range(5):
        time.sleep(1)
        x = x +1

peace = st.empty()

if 'key' not in st.session_state:
    with peace:
        if(st.button("Set Key")):
            longproc()
            st.session_state['key'] = 'value'


if 'key' in st.session_state:
    peace.empty()
    st.write(st.session_state.key)
    if(st.button("Set New")):
        st.write("new")   

Hi anyone knows how to get the source code of this app New app - Search Youtube videos by text expresstube app. i want a similar feature to be implemented. I could not reply in same chain as it was closed. Tia