Reacting to metadata changes? it seems like it’s perfectly possible to get re-renders when the metadata of the contents of a ratom changes, but if I create a cursor to that same content, I don’t get any re-renders. It seems to me like ratoms and cursors should act the same in this regard, so why the difference?
to be fair, me trying to use metadata in this way might be trying to hack the system, I just found it odd that it would work for ratoms, but not for cursors. I guess they have different equality checks?
Some code example could be helpful to explaining this. How do you update the metadata on Ratom value?
Here’s an example:
(defonce ra
(r/atom (with-meta [] {:i 0})))
(defonce ra-for-rc
(r/atom {:a {:b {:c (with-meta [] {:i 0})}}}))
(defonce rc
(r/cursor ra-for-rc [:a :b :c]))
(defn ratom-vs-cursor
[]
[:div
[:p
[:button {:on-click #(swap! ra vary-meta update :i inc)}]
(-> @ra meta :i str)]
[:p
[:button {:on-click #(swap! rc vary-meta update :i inc)}]
(-> @rc meta :i str)]])
If I do with-meta
it doesn’t work either, but if I update the actual value at the same time, it will update just fine. It just doesn’t react to metadata updates, unlike the ratom.
RAtom implementation will notify change listeners (e.g. components and other reactions) whenever swap or reset is called, even if the value didn't change.
RCursor only notifies listeners if the value changes https://github.com/reagent-project/reagent/blob/master/src/reagent/ratom.cljs#L273-L277
This is so that RCursor doesn't trigger changes when the RAtom it depends on changes, but the value on the cursor path didn't change.
Not sure if it would make sense to always trigger when calling reset/swap on cursor. But this is very minor oddity.
I see. Thanks a lot for investigating. That sucks, because it kind of prevents me from doing something I had in mind (using metadata for incidental information like indices) if it can’t apply broadly.
I imagine you would get into trouble with metadata sooner or later either way - it's finicky, not many libraries or functions try to preserve it.
yeah, even clojure.core isn’t too consistent about it, but I just love the idea of attaching, well metadata like “what is the current index being viewed” to real data like a vector of content.
seems like a great way to semantically separate content
> content Metadata is not for that. It's a great way to shoot yourself in the foot. :)
Yeah I agree with @p-himik here. The selected index being viewed etc. is real data just like the vector or something, just place it it a map with the other data.