mirror of
https://github.com/penpot/penpot.git
synced 2026-10-29 05:50:35 +00:00
🐛 Stop thumbnail subscribers re-rendering on every store change
A thumbnail loaded from the server keeps a media id as :uri, and workspace-thumbnail-by-id resolves it into a new map on each read. The ref compared values with identical?, so every root frame, every component in the assets panel and the interactions layer re-rendered on every store change, mouse moves included. Compare by value instead. This does not loop by itself, but it adds work to every commit and brings other update loops closer to React's limit. Relates to #12580 AI-assisted-by: claude-opus-5-5
This commit is contained in:
parent
6508449fa0
commit
379470bdd2
@ -609,6 +609,8 @@
|
||||
|
||||
(defn workspace-thumbnail-by-id
|
||||
[object-id]
|
||||
;; Resolving a media id builds a new map on each read; compare by
|
||||
;; value so subscribers do not re-render on every store change.
|
||||
(l/derived
|
||||
(fn [state]
|
||||
(when-let [entry (dm/get-in state [:thumbnails object-id])]
|
||||
@ -616,7 +618,8 @@
|
||||
(and (:uri entry)
|
||||
(not (resolved-uri? (:uri entry))))
|
||||
(update :uri cf/resolve-media))))
|
||||
st/state))
|
||||
st/state
|
||||
=))
|
||||
|
||||
(def workspace-text-modifier
|
||||
(l/derived :workspace-text-modifier st/state))
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
(:require
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[cljs.test :as t :include-macros true]))
|
||||
|
||||
(def ^:private resolved-uri? @#'refs/resolved-uri?)
|
||||
@ -28,3 +29,23 @@
|
||||
(t/is (false? (resolved-uri? (uuid/next))))
|
||||
(t/is (false? (resolved-uri? nil)))
|
||||
(t/is (false? (resolved-uri? 42))))
|
||||
|
||||
(t/deftest thumbnail-ref-ignores-unrelated-state-changes
|
||||
;; A thumbnail loaded from the server keeps a media id as :uri, and
|
||||
;; the ref resolves it to a new map on each read. Subscribers (root
|
||||
;; frames, assets) must not re-render on every unrelated store change.
|
||||
(let [object-id (str (uuid/next))
|
||||
ref (refs/workspace-thumbnail-by-id object-id)
|
||||
calls (atom 0)]
|
||||
(swap! st/state assoc-in [:thumbnails object-id] {:uri (uuid/next) :rendered-at nil})
|
||||
(add-watch ref ::probe (fn [_ _ _ _] (swap! calls inc)))
|
||||
(try
|
||||
(swap! st/state assoc ::probe (uuid/next))
|
||||
(t/is (zero? @calls) "unrelated change does not notify")
|
||||
(swap! st/state assoc-in [:thumbnails object-id :uri] (uuid/next))
|
||||
(t/is (= 1 @calls) "a new thumbnail uri notifies")
|
||||
(finally
|
||||
(remove-watch ref ::probe)
|
||||
(swap! st/state #(-> %
|
||||
(dissoc ::probe)
|
||||
(update :thumbnails dissoc object-id)))))))
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user