From 63df8047cf95bcf8517bc0da25afff3f255be2ec Mon Sep 17 00:00:00 2001 From: scheinriese Date: Thu, 23 Apr 2026 14:49:59 +0200 Subject: [PATCH] fix: stabilize debounced web-query setter across renders MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The old (memoize (fn [] (debounce …))) built a fresh debouncer on every render, so each keystroke got its own timer and debouncing never actually happened — partial-prefix queries all fired, producing the race condition that request-id guards. Move the debounce into component state via :will-mount (not :init, because rum/local only installs the underlying atom during :will-mount) so a single timer persists across renders. --- src/main/frontend/components/icon.cljs | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/main/frontend/components/icon.cljs b/src/main/frontend/components/icon.cljs index 441859c25b..bfc452b187 100644 --- a/src/main/frontend/components/icon.cljs +++ b/src/main/frontend/components/icon.cljs @@ -2186,7 +2186,16 @@ (rum/local nil ::loaded-assets) ;; Cached assets loaded async (rum/local nil ::web-query-debounced) ;; Debounced web search query (rum/local false ::popover-open?) ;; Track if any popover is open - {:did-mount (fn [state] + ;; Create a single stable debounced setter. Must live in state (not the + ;; render `let`) so the debounce timer persists across renders — otherwise + ;; every keystroke gets a fresh timer and no debouncing happens, causing + ;; stale partial-prefix searches to race. Runs as :will-mount (not :init) + ;; because rum/local installs its atoms during :will-mount. + {:will-mount (fn [state] + (let [*web-query-debounced (::web-query-debounced state)] + (assoc state ::update-web-query! + (debounce (fn [q] (reset! *web-query-debounced q)) 500)))) + :did-mount (fn [state] ;; Track picker open state (reset! *asset-picker-open? true) @@ -2254,13 +2263,8 @@ assets)) asset-count (count filtered-assets) avatar-mode? (some? avatar-context) - ;; Debounced update of web query - update-web-query-debounced - (memoize - (fn [] - (debounce - (fn [q] (reset! *web-query-debounced q)) - 500))) + ;; Stable debounced web-query setter (created once in :init) + update-web-query! (::update-web-query! state) ;; SVG detection helper - checks if URL is an SVG file svg-url? (fn [url] @@ -2483,7 +2487,7 @@ (let [v (util/evalue e)] (reset! *search-q v) ;; Update debounced web query - ((update-web-query-debounced) v)))})]]] + (update-web-query! v)))})]]] ;; Body - scrollable content area with top/bottom margin (let [;; Get recently used asset UUIDs and resolve to asset entities