Hello,
Here is my use case :
In my app I want the user to be able to track the status of a thing. To do this I have a fragment that makes an api call and displays the result on screen, at first I want that fragment to refresh quickly, let’s say once a second, but then I want to strech the refresh time so I don’t get ten thousand API calls because someone left their page open.
At first I tried to make this happen with st.fragment(run_every=something) The issue here is that I am unable to change the “something” from within the fragment so I am locked to a single refersh rate.
My second idea was to do something like this :
import streamlit as st
import time
def main():
# Reset refresh rate
st.session_state.refresh_rate = 1
refreshing_subpage()
@st.fragment
def refreshing_subpage():
data = "some_api_call"
st.write(data)
time.sleep(st.session_state.refresh_rate)
st.session_state.refresh_rate += 1
st.rerun(scope="fragment")
if __name__ == "__main__":
main()
But with this I get :
streamlit.errors.StreamlitAPIException: scope="fragment" can only be specified from `@st.fragment`-decorated functions during fragment reruns.
My understanding is that this issue arises because when my fragment first runs it does so from a full page rerun, not a fragment rerun. This means I need to be in a fragment rerun to trigger a fragment rerun which kinda creates a chicken and egg problem.
The only other ways I know to enter a fragment rerun are the run_every parameter talked about earlier and user interaction. Since I don’t really want to have a big red button inside the fragment that says “CLICK ME PLEASE MY CODE WON’T WORK WHITOUT YOUR HELP” I tried other solutions.
I briefly considered having an invisible button that would get triggered by javascript to trigger the fragment rerun but that’s a bit too janky even for me. Ultimately what I ended up with is a having two different version of my display function, one decorated with a run_every and one whithout. The decorated version keeps track of the number of second passed and when it goes above x it trigger a full rerun that brings the user to the non-decorated non-refreshing version.
This is an imperfect and pretty janky solution.
I would love to know if there is a better way and if this is how rerun(scope=“fragment”) is intended to work.
Thank you in advance for your help.