Can Streamlit keep input variables when refreshing the browser

Hi there! My team and I are developing a demo for users to input some parameters, but I find that the input parameter can’t be saved when the browser refreshes.

I tried to use @st.cache, but it can’t save the input. (Maybe I used it wrong). Here is part of the code:

def set_parameters():
    st.session_state.maxDepth = st.number_input(label="maxDepth",min_value=2, max_value=10, step = 1)
    st.session_state.maxBreadth = st.number_input(label="maxBreadth", min_value=1, max_value=5, step=1)

How can I keep the input even after the browser refreshes?
Any help is appreciated!

Hi @Shawn_Sun , you could try saving to a local text file immediately after a user inputs data, and reading from the local file on application initialization. Check if that works.

Cheers

1 Like

If you give a key to your input widgets you can access their value via this key:

def set_parameters():
    st.number_input(label="maxDepth", key="maxDepth", min_value=2, max_value=10, step = 1)
    st.number_input(label="maxBreadth", key="maxBreadth", min_value=1, max_value=5, step=1)

set_parameters()
st.write(st.session_state.maxDepth)

@Shawn_Pereira It’s a good idea! But I’m still wondering if the sever suffers from I/O when there are enormous users. But for now, we can use that! Thank you!

Thank you @Philipp_Langen. But to access the value is kinda different from saving the value when the page reloads.

I am not 100% sure those components answer your question, because I don’t know if refreshing the browser kills the global session or if state stays server-wide anyway, maybe give them a try:

Hope to see your feedback on those
Fanilo

2 Likes

I think using st.experimental_set_query_params() and st.experimental_get_query_params() can be another option.

import streamlit as st


def read_values():
    urlparams = st.experimental_get_query_params()
    return {
        "maxDepth": int(urlparams["maxDepth"][0]) if "maxDepth" in urlparams else None,
        "maxBreadth": int(urlparams["maxBreadth"][0]) if "maxBreadth" in urlparams else None,
    }


def save_values():
    st.experimental_set_query_params(
        maxDepth=str(int(st.session_state.maxDepth)),
        maxBreadth=str(int(st.session_state.maxBreadth)),
    )


values = read_values()

st.number_input(label="maxDepth", key="maxDepth", value=values["maxDepth"] or 2, min_value=2, max_value=10, step=1, on_change=save_values)
st.number_input(label="maxBreadth", key="maxBreadth", value=values["maxBreadth"] or 1,  min_value=1, max_value=5, step=1, on_change=save_values)

Note that in this example, setting key to the widgets to access the values via the session state and calling save_values() as the on_change callback of the widgets are an important trick. It does not work well if save_values() is called simply at the bottom of the script. This is due to the execution flow of Stremalit script.

The underlying idea of this example is the same as @Shawn_Pereira 's, but the data store is different; this saves the data to URL params instead of the server storage.

URL params are visible to users, so don’t use this method for sensitive data.


I think saving and restoring data from the local files will encounter problems when the app has to manage multiple users, since the app can’t know the user identity when the user revisits. streamlit-server-state may have the same problem as it shares the data globally without user separation.

If your app is hosted on Streamlit Cloud, st.user can be used to get user identity though :+1:

If not, Cookie extension may help.

I thought the client-side Local Storage could also be a solution like URL query param and found Accessing Local Storage/ Session Storage in custom components. This thread did not reach the solution though, it may be possible with the current Streamlit API?

2 Likes

Thank you, Fanilo!
For our very simple framework, we decide to use a database to store some of the parameters. (And we don’t have to worry about the user scale). And your suggestions are very helpful to our future extension! Thanks!

1 Like

Hi @whitphx , thank you so much for the suggestion!
Since we’re not processing a large amount of data simultaneously, we implemented this auto-saving function by connecting to a database. But at the same time, we’ll do further experiments on what you suggested!
Thank you again for the detailed explanation! :+1:

1 Like