From 48f3bc1960d71785aad44292205845612a4f1cb8 Mon Sep 17 00:00:00 2001 From: Tyler Date: Sun, 17 May 2026 00:58:25 -0700 Subject: Fix persistence write-before-read and click swallow bugs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two root causes: 1. The JS wrote empty session defaults to localStorage before reading stored values back, destroying saved data on every fresh page load. Fixed by gating on data-loaded: JS reads+restores only when loaded=0, writes+saves only when loaded=1. 2. st.rerun() inside render_persistence_bridge() aborted the render before qt_click_receiver/wl_click_receiver were registered. Streamlit clears unrendered widget state, so pending click values (_qt_click, _wl_click) were wiped before quotetable/watchlist could process them. Fixed by removing st.rerun() — the bridge runs at the top of the render cycle so restored session state propagates to components below in the same pass; no extra rerun needed. Co-Authored-By: Claude Sonnet 4.6 --- components/persistence.py | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/components/persistence.py b/components/persistence.py index 1dafdbe..552347d 100644 --- a/components/persistence.py +++ b/components/persistence.py @@ -16,25 +16,24 @@ def render_persistence_bridge() -> None: if restored_tk: st.session_state["ticker"] = restored_tk st.session_state["_persist_loaded"] = True - st.rerun() + # No st.rerun() — the bridge runs at the top of the render cycle so the + # restored values propagate naturally to components below. Calling + # st.rerun() here would abort the render before click-receiver inputs + # (qt_click_receiver, wl_click_receiver) are registered, causing + # Streamlit to clear their pending values and swallow the click. st.text_input("persist_wl", key="_persist_wl", label_visibility="collapsed") st.text_input("persist_tk", key="_persist_tk", label_visibility="collapsed") + loaded = "1" if st.session_state.get("_persist_loaded") else "0" wl_json = escape_html(json.dumps(st.session_state.get("watchlist", []))) tk_val = escape_html(st.session_state.get("ticker") or "") html = ( - "
" + "
" "" ) -- cgit v1.3-2-g0d8e