Hi team,
Does the new session_state feature resolves the issue of app getting reset while using two buttons? My app’s 2nd button click actually resets the entire app and takes me back to the state where the first button was not pressed.
Does the session_state helps to use both the buttons? Can anyone share an example please?
Thanks!
Disclaimer: Novice streamlit user
Hello @arindam, welcome to the forum!
Yes it does! Now there is many ways to solve this issue.
Let’s take this basic non-working example:
import streamlit as st
data = []
if st.button("Load data"):
data = ["This", "Is", "My", "Data"]
if st.button("Uppercase data"):
data = [item.upper() for item in data]
st.write(data)
Behind that pattern, the idea is to divide the app in multiple sequential step, eventually taking parameters between steps to choose and filter some data.
So we must make sure to go from one step to another, while keeping our data and without executing the previous steps as our script reruns from the beginning.
import streamlit as st
# An alias for our state
state = st.session_state
# A function to easily go from one step to another
def change_step(next_step):
state.step = next_step
# Let's initialize our session state
if "data" not in state:
state.data = []
state.step = "init"
# Step 1
if state.step == "init":
st.button("Load data", on_click=change_step, args=["load"])
# Step 2
if state.step == "load":
state.data = ["This", "Is", "My", "Data"]
st.button("Uppercase data", on_click=change_step, args=["upper"])
# Step 3
if state.step == "upper":
state.data = [item.upper() for item in state.data]
# We print our data everytime
st.write(state.data)
Thanks for the quick reply @okld . But somehow I still can’t manage to do this. It is still refreshing my app on 2nd button click.
My code is a bit long, not sure how to send the code as a file here.
One thing I have in my code is the 2nd button is inside a nested if condition. The initial if condition has a Submit button and once that submit button is clicked, it does some processing and goes to a download button within that if condition. Now when I click the Download button, it refreshes entire app.
Thanks
You could try the following in your case:
import streamlit as st
if "submitted" not in st.session_state:
st.session_state.submitted = False
if st.button("Submit") or st.session_state.submitted:
st.session_state.submitted = True
if st.button("Download"):
st.session_state.submitted = False
st.write("Download clicked!")
If needed, you can upload your code on GitHub Gist (or Pastebin if you don’t have a github account) and share the link here.
@okld @arindam
Thanks for bringing this conversation and addressing this issue, really helpful for beginner Streamlit users like me.
So I am currently facing a challenge. I am working towards building a multi-page like streamlit app with the help of buttons.
From the sidebar when a button like button1 is pressed I want the app to display another set of buttons like bb1 in my case and when that is clicked display some plot.
Similarly I want to display bb2 when button2 is clicked and when bb2 is clicked display some chart.
I have used the code below but here when I click button 1 both bb1 and bb2 are showing up. Could you please help me with a fix or sample code to work on the same.
session_state1 = SessionState.get(checkboxed=False)
session_state2 = SessionState.get(checkboxed=False)
tday = st.sidebar.date_input('Date Input')
lc, mc, rc = st.columns(3)
button1 = st.sidebar.button("Open Interest")
button2 = st.sidebar.button("FII/DII Data")
button3 = st.sidebar.button("Trading Strategy")
if button1 or session_state1.checkboxed:
session_state1.checkboxed = True
df = fnodata(tday)
option = lc.selectbox(
'Symbol',
df['SYMBOL'].unique())
option_exp = mc.selectbox(
'Expiry DATE',
df['EXPIRY_DT'].unique())
option_inst = rc.selectbox(
'INSTRUMENT',
df['INSTRUMENT'].unique())
#Getting CMP
gcmp = get_cmp(df, option)
# Graph data as per user choice
filterdata = filtered_data(df, option, option_exp, option_inst, gcmp)
bb1 = lc.button("Generate OI Graphs")
if bb1:
session_state1.checkboxed = False
oi_chart = oi_chart_graph(filterdata)
coi_chart = coi_chart_graph(filterdata)
# Plotting OI Graph
st.plotly_chart(oi_chart)
# Plotting OI Change Graph
st.plotly_chart(coi_chart)
if button2 or session_state2.checkboxed:
session_state2.checkboxed = True
df1 = fiidiidata(tday)
client_type = lc.selectbox('Client',
df1['Client Type'].unique())
date_fii = rc.selectbox('Contract Date',
df1['Date'].unique())
bb2 = rc.button("Generate FII Graphs")
if bb2:
session_state2.checkboxed = False
fii_chart = get_fii_chart(df1)
st.plotly_chart(fii_chart)
st.write(df1.tail())
In short, I need help with a sample code that is able to do the following:
-
Display 3 buttons on the sidebar which I have been able to do.
-
Display bb1 when button 1 is clicked, and when this bb1 is clicked display a set of graphs.
-
Display bb2 when button 2 is clicked, and when this bb2 is clicked display another set of graphs.
My code is showing both bb1 and bb2 when button1 is clicked.
Thanks a lot for taking out time and reading this!
Hello @pitanjal,
Is there a reason you use the old SessionState hack instead of the new st.session_state
implementation?
That said, SessionState
is a singleton, which means that in your app you can have only one instance of it.
So when you create your two session_state1
and session_state2
, they actually reference the same SessionState
object, and checkboxed
will be the same for your two buttons.
Ideally you’d do something like this:
# Using the new st.session_state
if "button1_clicked" not in st.session_state:
st.session_state.button1_clicked = False
st.session_state.button2_clicked = False
# Or if for some reason you cannot use it, here's with the old version
session_state = SessionState.get(
button1_clicked=False,
button2_clicked=False,
)
Then in your conditions you’d do:
if button1 or st.session_state.button1_clicked:
# ...
# With the old session state, just drop the `st.`
if button1 or session_state.button1_clicked:
# ...
Hey @okld ,
Thank You so much for guiding me and helping me with this. I have tried your technique and it is working perfectly now.
Also, thanks for making me aware of the new streamlit st.session_state, I will keep using that from now on.
Thank You so much, once again!
@okld Did someone say that you are a Champ? That was an awesome solution and many thanks for rescuing me from hitting my head in the wall
I will close this thread, much appreciated.