How to make session_state updated when I select a point on plotly_chart

HI everyone,
I have this use case where I have a plotlychart :

import streamlit as st
import plotly.express as px

if "var" not in st.session_state:
    st.session_state["var"] = 0

col3,col4 = st.columns(2)


def plot():
    df = px.data.iris()
    fig = px.scatter(
    df,
    x="sepal_width",
    y="sepal_length",
    color="species",
    size="petal_length",
    hover_data=["petal_width"],
     )

    event = st.plotly_chart(fig, key="iris", on_select="rerun")
    event.selection
    if len(event.selection.points)!=0:
         st.session_state["var"] = event.selection.points[0]["x"]
        #  st.rerun()
        

with col3:
    st.write(st.session_state["var"])

with col4:
    plot()

my issue is when I select a point on the graph, logically the st.session_state["var"] should be updated directly …but it is not the case here…I have tried to use st.rerun() but it is enter in infinity loop…do you have any idea please to make st.session_state["var"] updated directly when I select a point ?
I want to keep the order of cols as it is.
thanks

I just tried this myself using your code and I’m getting the point to return (I’m running it on streamlit cloud), so I’m guessing it’s unique to your environment. I know this is dumb, but if you try rebooting does that help? Or worst case, recreate the project?

Before clicking:

After clicking a point:

thanks for your time, I think you do not understant the issua.
the issue is st.session_state["var"] on the left does not updated with the x value…there a delay, try to click a bubble and see the st.session_state["var"] you will see that it is not updated. try that on your own.(see the pictire below)

I see, sorry about the confusion

So you might understand this, but without having the session state update in a callback from st.plotly_chart, I wouldn’t expect that value to update immediately. Instead, it will lag one behind, so if you click a second point, you will then see that value update to the first point you clicked

This happens because the entire code re-runs top to bottom when you click a point and plot() isn’t hit until after you write the “var” session state

Instead, you can do this, which captures the point in “var” with a callback and then re-runs

import streamlit as st
import plotly.express as px

if "var" not in st.session_state:
    st.session_state["var"] = 0

col3, col4 = st.columns(2)


def _update_session_state():
    event = st.session_state.iris
    if len(event.selection.points) != 0:
        st.session_state["var"] = event.selection.points[0]["x"]


def plot():
    df = px.data.iris()
    fig = px.scatter(
        df,
        x="sepal_width",
        y="sepal_length",
        color="species",
        size="petal_length",
        hover_data=["petal_width"],
    )

    st.plotly_chart(fig, key="iris", on_select=_update_session_state)


with col3:
    st.write(st.session_state["var"])

with col4:
    plot()
1 Like

I dont know How I midded that…thnak so much…:wink:

1 Like

@msquaredds is there a chance to pass some parameters to _update_session_state like the df as example.?
I tried this :

def _update_session_state(df):
    st.dataframe(df)
    event = st.session_state.plotgraph
    if len(event.selection.points) != 0:
        st.session_state["var"] = event.selection.points[0]["x"]


def plot():
    df = px.data.iris()
    fig = px.scatter(
        df,
        x="sepal_width",
        y="sepal_length",
        color="species",
        size="petal_length",
        hover_data=["petal_width"],
    )

    event=st.plotly_chart(fig, key="plotgraph", on_select=_update_session_state,args=(df,))
    event


with col3:
    st.write(st.session_state["var"])

with col4:
    plot()

but it gives this error :
TypeError: _update_session_state() missing 1 required positional argument: 'df'

do you know why please ?

That’s interesting, I haven’t used the callback with plotly_chart all that much, but it seems to be one of the few widgets in streamlit that doesn’t accept args. What you’re doing looks correct for almost any other widget

In this case, I think you would have to use session state, like so:

def _update_session_state(df):
    df = st.session_state.df
    st.dataframe(df)
    event = st.session_state.plotgraph
    if len(event.selection.points) != 0:
        st.session_state["var"] = event.selection.points[0]["x"]


def plot():
    df = px.data.iris()
    fig = px.scatter(
        df,
        x="sepal_width",
        y="sepal_length",
        color="species",
        size="petal_length",
        hover_data=["petal_width"],
    )

    st.session_state.df = df
    event=st.plotly_chart(fig, key="plotgraph", on_select=_update_session_state)
    event


with col3:
    st.write(st.session_state["var"])

with col4:
    plot()
1 Like

thanks a lot :wink: fo your help and time.

I was also looking for something similar, one thing that I have noticed it that with every user interaction the chart is re-rendered, how to control this behavior ?

Thanks for your discussion , it helped

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.