On_click callback doesn't update session state plots


I’m struggling with updating plots through an on_click callback in a session state.
The callback executes as it should (generates new data frame and plots) and I can access updated plots by a different name in the session state but it doesn’t update already initially generated plots, breaking the flow.

Is there a simpler way to execute this than the code below?


Code snippet:

page2_container = st.container()

def update_figures():
    objectName.value  = new_value
    updated_data = objectName.generate_data()  # with new_value

    updated_plot_a = objectName.generate_plot_a(updated_data)
    updated_plot_b = objectName.generate_plot_b(updated_data)

    # I want to display these updated plots
    st.session_state.figures.update({'PLOT_A': updated_plot_a})
    st.session_state.figures.update({'PLOT_B': updated_plot_b})

with st.sidebar:
    value = st.number_input(
        label='Select value', 
        on_change=update_figures)  # callback

objectName = moduleName.className(...)
data_diff = testObject.generate_data()

plot_a = testObject.generate_plot_a(data_diff)
plot_b = testObject.generate_plot_b(data_diff)

st.session_state.figures.update({'PLOT_A': plot_a})
st.session_state.figures.update({'PLOT_B': plot_b})

with page2_container:
    with st.container():
        left, right = st.columns([1, 1])
        with left:
            st.plotly_chart(st.session_state.figures['PLOT_A'])  # displays initially generated plot
        with right:
            st.plotly_chart(st.session_state.figures['PLOT_B']) # displays initially generated plot

I’m not sure I completely understand which parts are working or not for you, or where you are pulling new_value from, so apologies if this is nothing helpful:

The two things that I think might be of interest is understanding the order of operations on the callback, and making sure you don’t reinitialize something on the page reload.

For callbacks, the precise order is:

value = st.number_input('Select Value', value=0, key="my_value", on_change=my_function)
  1. Assignment of the selection to st.session_state.my_value (The key is auto-generated if you don’t specify it as an optional keyword argument in your input widget.)
  2. Execution of the callback function. If you need to access the selection within the callback function, you’ll need to pull it from st.session_state.my_value. (You’ll need to have a specified key if you want to conveniently access the selected value in the callback function.)
  3. Page reloads…and you’ll get the selection as an output of the widget (assignment to variable value in this example) as a result. All your other code (even the initializing code) will rerun without conditionals to stop them.

If you have some code that initializes something in session state, make sure you put that inside a conditional so that is only runs if the data isn’t already there. Otherwise, even if you updated previously, it will keep getting reinitialized when the page reloads.

It was the page reload and initialisation! Solved!