Skip to content

Commit 7a71115

Browse files
committed
fix unmount bug
1 parent ab2a826 commit 7a71115

3 files changed

Lines changed: 33 additions & 18 deletions

File tree

core/src/refx/hooks.cljs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
(react/useMemo
2929
(fn []
3030
[(fn [callback]
31-
(let [key {:index (swap! use-sub-counter inc)}]
31+
(let [key {::subs/index (swap! use-sub-counter inc)}]
3232
(subs/-add-listener sub key callback)
3333
#(subs/-remove-listener sub key)))
3434
(fn []

core/src/refx/subs.cljc

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,13 @@
6464
(cache-remove! (-query-v sub) sub)
6565
(-dispose! sub))
6666

67+
(defn- ui-sub?
68+
"UI subscriptions are batched together and invoked after all subs
69+
finish computing their new values. This is done to reduce renders and
70+
prevent consumers from having an inconsistent view of the DB."
71+
[sub-key]
72+
(some? (::index sub-key)))
73+
6774
;; TODO This could be changed to support "garbage collection": Don't dispose
6875
;; right away, but keep subscriptions around for a while in case they are
6976
;; requested again.
@@ -78,7 +85,7 @@
7885

7986
(defonce ^:private listeners-state
8087
(letfn [(comparator [a b]
81-
(compare (:index a) (:index b)))]
88+
(compare (::index a) (::index b)))]
8289
(atom {:counter 0 :pending (sorted-map-by comparator)})))
8390

8491
(defn- invoke-listener
@@ -103,16 +110,20 @@
103110

104111
(interop/next-tick
105112
(fn []
106-
(let [listener-fns (atom nil)]
107-
(swap! listeners-state (fn [state]
108-
(let [{:keys [counter pending] :as new-state}
109-
(update state :counter dec)]
110-
(if (zero? counter)
111-
(do (reset! listener-fns pending)
112-
(update new-state :pending empty))
113-
new-state))))
114-
(doseq [[_ f] @listener-fns]
115-
(f)))))))
113+
(let [{:keys [counter pending]}
114+
(swap! listeners-state update :counter dec)]
115+
116+
(when (zero? counter)
117+
(doseq [[listener-key _] pending]
118+
;; Triggering a listener-fn can result in a subsequent sub's
119+
;; remove-listener to be called (which will remove it from pending).
120+
;; This check ensure it's still pending.
121+
(let [listener-fn (atom nil)]
122+
(swap! listeners-state (fn [state]
123+
(reset! listener-fn (get-in state [:pending listener-key]))
124+
(update state :pending dissoc listener-key)))
125+
(when-let [f @listener-fn]
126+
(f))))))))))
116127

117128
(deftype Listeners [^:mutable listeners]
118129
Object
@@ -160,6 +171,8 @@
160171
(-add-listener [_ k f]
161172
(.add listeners k f))
162173
(-remove-listener [this k]
174+
(when (ui-sub? k)
175+
(swap! listeners-state update :pending dissoc k))
163176
(.remove listeners k)
164177
(when (.empty? listeners)
165178
(sub-orphaned this)))
@@ -238,6 +251,8 @@
238251
(-add-listener [_ k f]
239252
(.add listeners k f))
240253
(-remove-listener [this k]
254+
(when (ui-sub? k)
255+
(swap! listeners-state update :pending dissoc k))
241256
(.remove listeners k)
242257
(when (.empty? listeners)
243258
(sub-orphaned this)))

core/test/refx/subs_test.cljs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@
119119
listener-calls (atom [])
120120
remove-listener-fns (atom '())
121121
add-listener! (fn [sub]
122-
(let [key {:index (swap! listener-count inc)}]
122+
(let [key {::subs/index (swap! listener-count inc)}]
123123
(subs/-add-listener sub key #(swap! listener-calls conj key))
124124
(swap! remove-listener-fns conj #(subs/-remove-listener sub key))))
125125
remove-listeners! (fn []
@@ -130,13 +130,13 @@
130130
(add-listener! sub-c)
131131
(add-listener! sub-d)
132132
(reset! source 1)
133-
(remove-listeners!)
134133
(async done
135134
(js/setTimeout (fn []
135+
(remove-listeners!)
136136
(is (= @listener-calls
137-
[{:index 1}
138-
{:index 2}
139-
{:index 3}
140-
{:index 4}]))
137+
[{::subs/index 1}
138+
{::subs/index 2}
139+
{::subs/index 3}
140+
{::subs/index 4}]))
141141
(done))
142142
10)))))

0 commit comments

Comments
 (0)