From 93f259060ace6118bf181a09dff4d2155487824c Mon Sep 17 00:00:00 2001 From: Juho Teperi Date: Fri, 3 Sep 2021 16:08:46 +0300 Subject: [PATCH] Test two ways to get regular atoms work in reactive context Related to #546 --- src/reagent/ratom.cljs | 66 +++++++++++++++++++++++++++++++++ test/reagenttest/testratom.cljs | 45 ++++++++++++++++++++++ 2 files changed, 111 insertions(+) diff --git a/src/reagent/ratom.cljs b/src/reagent/ratom.cljs index 638c2a32..349b628b 100644 --- a/src/reagent/ratom.cljs +++ b/src/reagent/ratom.cljs @@ -628,3 +628,69 @@ (flush!))) (dispose! res)))) (ratom-perf)) + +(deftype WrappedAtom [x] + IAtom + IReactiveAtom + + IEquiv + (-equiv [o other] (identical? o other)) + + IDeref + (-deref [this] + (notify-deref-watcher! x) + @x) + + IReset + (-reset! [a new-value] + (reset! x new-value)) + + ISwap + (-swap! [a f] (swap! x f)) + (-swap! [a f x] (swap! x f x)) + (-swap! [a f x y] (swap! x f x y)) + (-swap! [a f x y more] (swap! x f x y more)) + + IWithMeta + (-with-meta [_ new-meta] + (WrappedAtom. (with-meta x new-meta))) + + IMeta + (-meta [_] (meta x)) + + IPrintWithWriter + (-pr-writer [a w opts] (pr-atom a w opts "WrappedAtom" {:atom x})) + + IWatchable + (-notify-watches [this old new] (-notify-watches x old new)) + (-add-watch [this key f] (-add-watch x key f)) + (-remove-watch [this key] (-remove-watch x key)) + + IHash + (-hash [this] (goog/getUid this))) + +(defn ->ratom + "Wraps Atom like object so that it notifies current reactive context + on deref. + + The object must implement be a cljs.core.Atom or + implement IDeref, IWatchable, IReset, ISwap, IMeta and IWithMeta." + [v] + (WrappedAtom. v)) + +;; Or: +;; Both wouldn't be implemented, but not sure right now which +;; is better. + +;; TODO: Better name +(defn reagent-deref + "Deref a Atom and register watcher to current Reactive + context, so that the context will be notified if the Atom + value is updated. + + This will enable using Atom in place of RAtom and Reactions, + as long as you remember to use this function instead of directly + dereferecing the Atom." + [a] + (notify-deref-watcher! a) + @a) diff --git a/test/reagenttest/testratom.cljs b/test/reagenttest/testratom.cljs index cbc0ca4e..61031cae 100644 --- a/test/reagenttest/testratom.cljs +++ b/test/reagenttest/testratom.cljs @@ -483,3 +483,48 @@ (pr-str (r/track (fn foo [] (:foo @x)))))) (is (= "#object[reagent.ratom.Reaction {:val 1}]" (pr-str (reaction (:foo @x))))))) + +(deftest adapt-regular-atom-test + (testing "WrappedAtom" + (let [runs (running) + start (rv/->ratom (atom 0)) + sv (reaction @start) + comp (reaction @sv (+ 2 @sv)) + c2 (reaction (inc @comp)) + count (rv/atom 0) + out (rv/atom 0) + res (reaction + (swap! count inc) + @sv @c2 @comp) + const (run! + (reset! out @res))] + (is (= @count 1) "constrain ran") + (is (= @out 2)) + (reset! start 1) + (r/flush) + (is (= @out 3)) + (is (<= 2 @count 3)) + (dispose const) + (is (= (running) runs)))) + + (testing "reagent-deref" + (let [runs (running) + start (atom 0) + sv (reaction (rv/reagent-deref start)) + comp (reaction @sv (+ 2 @sv)) + c2 (reaction (inc @comp)) + count (rv/atom 0) + out (rv/atom 0) + res (reaction + (swap! count inc) + @sv @c2 @comp) + const (run! + (reset! out @res))] + (is (= @count 1) "constrain ran") + (is (= @out 2)) + (reset! start 1) + (r/flush) + (is (= @out 3)) + (is (<= 2 @count 3)) + (dispose const) + (is (= (running) runs)))))