Skip to content

Commit

Permalink
fix unmount bug
Browse files Browse the repository at this point in the history
  • Loading branch information
dehli committed Jul 11, 2024
1 parent ab2a826 commit 90e02dd
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 18 deletions.
2 changes: 1 addition & 1 deletion core/src/refx/hooks.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
(react/useMemo
(fn []
[(fn [callback]
(let [key {:index (swap! use-sub-counter inc)}]
(let [key {::subs/index (swap! use-sub-counter inc)}]
(subs/-add-listener sub key callback)
#(subs/-remove-listener sub key)))
(fn []
Expand Down
30 changes: 19 additions & 11 deletions core/src/refx/subs.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@

(defonce ^:private listeners-state
(letfn [(comparator [a b]
(compare (:index a) (:index b)))]
(compare (::index a) (::index b)))]
(atom {:counter 0 :pending (sorted-map-by comparator)})))

(defn- invoke-listener
Expand All @@ -103,16 +103,20 @@

(interop/next-tick
(fn []
(let [listener-fns (atom nil)]
(swap! listeners-state (fn [state]
(let [{:keys [counter pending] :as new-state}
(update state :counter dec)]
(if (zero? counter)
(do (reset! listener-fns pending)
(update new-state :pending empty))
new-state))))
(doseq [[_ f] @listener-fns]
(f)))))))
(let [{:keys [counter pending]}
(swap! listeners-state update :counter dec)]

(when (zero? counter)
(doseq [[listener-key _] pending]
;; Triggering a listener-fn can result in a subsequent sub's
;; remove-listener to be called (which will remove it from pending).
;; This check ensure it's still pending.
(let [listener-fn (atom nil)]
(swap! listeners-state (fn [state]
(reset! listener-fn (get-in state [:pending listener-key]))
(update state :pending dissoc listener-key)))
(when-let [f @listener-fn]
(f))))))))))

(deftype Listeners [^:mutable listeners]
Object
Expand Down Expand Up @@ -160,6 +164,8 @@
(-add-listener [_ k f]
(.add listeners k f))
(-remove-listener [this k]
(when-not (signal? k)
(swap! listeners-state update :pending dissoc k))
(.remove listeners k)
(when (.empty? listeners)
(sub-orphaned this)))
Expand Down Expand Up @@ -238,6 +244,8 @@
(-add-listener [_ k f]
(.add listeners k f))
(-remove-listener [this k]
(when-not (signal? k)
(swap! listeners-state update :pending dissoc k))
(.remove listeners k)
(when (.empty? listeners)
(sub-orphaned this)))
Expand Down
12 changes: 6 additions & 6 deletions core/test/refx/subs_test.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@
listener-calls (atom [])
remove-listener-fns (atom '())
add-listener! (fn [sub]
(let [key {:index (swap! listener-count inc)}]
(let [key {::subs/index (swap! listener-count inc)}]
(subs/-add-listener sub key #(swap! listener-calls conj key))
(swap! remove-listener-fns conj #(subs/-remove-listener sub key))))
remove-listeners! (fn []
Expand All @@ -130,13 +130,13 @@
(add-listener! sub-c)
(add-listener! sub-d)
(reset! source 1)
(remove-listeners!)
(async done
(js/setTimeout (fn []
(remove-listeners!)
(is (= @listener-calls
[{:index 1}
{:index 2}
{:index 3}
{:index 4}]))
[{::subs/index 1}
{::subs/index 2}
{::subs/index 3}
{::subs/index 4}]))
(done))
10)))))

0 comments on commit 90e02dd

Please sign in to comment.