Skip to content

Commit 5baa4cf

Browse files
committed
Try using flushSync when flushing Reagent render queue
This will avoid double queuing when Reagent has already queued components to render due to ratom changes.
1 parent ce2c505 commit 5baa4cf

File tree

2 files changed

+20
-4
lines changed

2 files changed

+20
-4
lines changed

src/reagent/dom/client.cljs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
(ns reagent.dom.client
22
(:require ["react" :as react]
33
["react-dom/client" :as react-dom-client]
4+
["react-dom" :as react-dom]
45
[reagent.impl.batching :as batch]
56
[reagent.impl.protocols :as p]
67
[reagent.impl.template :as tmpl]
@@ -52,6 +53,7 @@
5253
([^js root el]
5354
(render root el tmpl/*current-default-compiler*))
5455
([^js root el compiler]
56+
(set! batch/react-flush react-dom/flushSync)
5557
(let [comp (fn [] (p/as-element compiler el))
5658
js-props #js {}]
5759
(set! (.-comp js-props) comp)
@@ -62,6 +64,7 @@
6264
(hydrate-root container el nil))
6365
([container el {:keys [compiler on-recoverable-error identifier-prefix]
6466
:or {compiler tmpl/*current-default-compiler*}}]
67+
(set! batch/react-flush react-dom/flushSync)
6568
(let [js-props #js {}
6669
comp (fn [] (p/as-element compiler el))]
6770
(set! (.-comp js-props) comp)

src/reagent/impl/batching.cljs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,27 @@
2929
(- (.-cljsMountOrder c1)
3030
(.-cljsMountOrder c2)))
3131

32+
;; See reagent.dom.client/render and hydrate-root
33+
;;
34+
;; On React 19 react-dom/flushSync is used to flush all Reagent ratom changes
35+
;; to DOM right away, to avoid double batching for these.
36+
;; React strongly recommends to avoid flushSync, but run-queue is
37+
;; used just once per animation frame and only when there were component
38+
;; re-renders triggered from ratom changes, so maybe this is fine.
39+
(defonce react-flush
40+
(fn noop [f]
41+
(f)))
42+
3243
(defn run-queue [a]
3344
;; sort components by mount order, to make sure parents
3445
;; are rendered before children
3546
(.sort a compare-mount-order)
36-
(dotimes [i (alength a)]
37-
(let [^js/React.Component c (aget a i)]
38-
(when (true? (.-cljsIsDirty c))
39-
(.forceUpdate c)))))
47+
(react-flush
48+
(fn []
49+
(dotimes [i (alength a)]
50+
(let [^js/React.Component c (aget a i)]
51+
(when (true? (.-cljsIsDirty c))
52+
(.forceUpdate c)))))))
4053

4154

4255
;; Set from ratom.cljs

0 commit comments

Comments
 (0)