Delay in getting and setting widget values as session state variables

Summary

I am utilizing the component clickable_images, and saving the clicked state as a session state var, however when rendering this val in a widget, e.g. text_area, I am experiencing a delay by 1 click offset, why is that? How can I update both the session state var and all the places it is rendered (on the website) at the same time so there’s no delay.

Code snippet:

import streamlit as st
from st_clickable_images import clickable_images

if "clicked" not in st.session_state:
    st.session_state.clicked = -1

st.text_area("init", placeholder=st.session_state.clicked, value=st.session_state.clicked)

st.session_state.clicked = clickable_images(
    [
        "https://images.unsplash.com/photo-1565130838609-c3a86655db61?w=700",
        "https://images.unsplash.com/photo-1565372195458-9de0b320ef04?w=700",
        "https://images.unsplash.com/photo-1582550945154-66ea8fff25e1?w=700",
        "https://images.unsplash.com/photo-1591797442444-039f23ddcc14?w=700",
        "https://images.unsplash.com/photo-1518727818782-ed5341dbd476?w=700",
    ],
    titles=[f"Image #{str(i)}" for i in range(5)],
    div_style={"display": "flex", "justify-content": "center", "flex-wrap": "wrap"},
    img_style={"margin": "5px", "height": "200px"},
)

st.markdown(f"Image #{st.session_state.clicked} clicked" if st.session_state.clicked > -1 else "No image clicked")

Attempts:

I tried using another session state variable, and saw that the st.write value is updated correctly so then how come the text_area value/placeholder isn’t?? There’s evidently something I’m not understanding about session state variables.

import streamlit as st
from st_clickable_images import clickable_images

if "clicked" not in st.session_state:
    st.session_state.clicked = -1

if "text" not in st.session_state:
    st.session_state.text = "empty"

st.text_area("init", placeholder=st.session_state.text, value=st.session_state.text)

st.session_state.clicked = clickable_images(
    [
        "https://images.unsplash.com/photo-1565130838609-c3a86655db61?w=700",
        "https://images.unsplash.com/photo-1565372195458-9de0b320ef04?w=700",
        "https://images.unsplash.com/photo-1582550945154-66ea8fff25e1?w=700",
        "https://images.unsplash.com/photo-1591797442444-039f23ddcc14?w=700",
        "https://images.unsplash.com/photo-1518727818782-ed5341dbd476?w=700",
    ],
    titles=[f"Image #{str(i)}" for i in range(5)],
    div_style={"display": "flex", "justify-content": "center", "flex-wrap": "wrap"},
    img_style={"margin": "5px", "height": "200px"},
)

st.markdown(f"Image #{st.session_state.clicked} clicked" if st.session_state.clicked > -1 else "No image clicked")

if st.session_state.clicked > -1:
    st.session_state.text = f"last clicked {st.session_state.clicked}" 

st.write(st.session_state.text)

Component
Link to clickable_images component: GitHub - vivien000/st-clickable-images

I am experiencing this delay in using st.session_state variables as a value in widgets in other use cases as well. Would appreciate an explanation as to why this occurs.

Is there anyway I can mimic a callback function without having to use a widget that has on_click attribute, for example? How come on_click callbacks update state session variables without a delay. Sorry if this sounds stupid…

@Goyo

I don’t think I understand the issue. If you can show an example using only standard streamlit widgets I will try to take a look at it.

I know this is a really late reply, but for posterity if someone comes across this:

In your first code snippet, say the page has loaded and st.session_state.clicked is currently -1.

  1. A user clicks an image.
  2. The page starts to rerun.
  3. st.text_area loads with st.session_state.clicked still equal to -1.
  4. st.session_state.clicked is updated.
  5. The updated value of st.session_state.clicked is displayed in markdown at the end of the page.

If the same selection is made again, the page will reload again, and then you would see the updated value in st.text_area. It takes two clicks because st.text_area is executed before the line that actually updates st.session_state.clicked.