Skip to content

cursor watch not triggering when base atom is swapped. #244

@retrogradeorbit

Description

@retrogradeorbit

When a watch is added to a cursor it only triggers when the cursor is changed directly with a swap!. It doesn't trigger when a change is achieved by swap!ing the base atom.

This code:

(def test-ratom (reagent/atom {:foo {:a 1} :bar {:b 10}}))

(defn watcher-debug [k a o n] (.log js/console "[WATCH]->" k a o n))

(def foo-cursor (reagent/cursor test-ratom [:foo]))
(def bar-cursor (reagent/cursor test-ratom [:bar]))

(add-watch foo-cursor :foo-watcher watcher-debug)
(add-watch bar-cursor :bar-watcher watcher-debug)

(println "swap! :foo via base ratom...")
(swap! test-ratom assoc-in [:foo :a] 2)

(println "swap! :foo via :foo cursor...")
(swap! foo-cursor assoc :a 3)

(println "swap! :bar via base ratom...")
(swap! test-ratom assoc-in [:bar :b] 11)

(println "swap! :bar via :bar cursor...")
(swap! bar-cursor assoc :b 12)

(println "swap! both :foo and :bar via base ratom...")
(swap! test-ratom #(-> %
                       (assoc-in [:foo :a] 4)
                       (assoc-in [:bar :b] 13)))

demonstrates the watches only firing on direct swaps.

swap! :foo via base ratom...
swap! :foo via :foo cursor...
[WATCH]-> foo-watcher 
r…t.r…m.Reaction {state: c…s.c…e.PersistentArrayMap, dirty_QMARK_: true, active_QMARK_: false, watching: null, watches: c…s.c…e.PersistentHashMap…}
 null Object {a: 2}
[WATCH]-> foo-watcher 
r…t.r…m.Reaction {state: c…s.c…e.PersistentArrayMap, dirty_QMARK_: true, active_QMARK_: false, watching: null, watches: c…s.c…e.PersistentHashMap…}
 Object {a: 2} Object {a: 3}
swap! :bar via base ratom...
swap! :bar via :bar cursor...
[WATCH]-> bar-watcher 
r…t.r…m.Reaction {state: c…s.c…e.PersistentArrayMap, dirty_QMARK_: true, active_QMARK_: false, watching: null, watches: c…s.c…e.PersistentHashMap…}
 null Object {b: 11}
[WATCH]-> bar-watcher 
r…t.r…m.Reaction {state: c…s.c…e.PersistentArrayMap, dirty_QMARK_: true, active_QMARK_: false, watching: null, watches: c…s.c…e.PersistentHashMap…}
 Object {b: 11} Object {b: 12}
swap! both :foo and :bar via base ratom...

Also note that on first cursor swap! the watcher is called twice. once from nil to the base value. And then once from the base value to the new value.

The behaviour should be consistent with base atom behaviour.

  1. When the base atom is changed, that should flow through to the cursor and trigger its watch
  2. The first cursor swap should only trigger one watch callback, from the old base value, to the new value.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions