Fork me on GitHub
#reagent
<
2017-09-19
>
l1sp3r13:09:18

if I assoc the same value under the same path twice to a ratom, will a subsciption deref fire twice?

carly15:09:15

As far as I understand it should not fire twice.

vinai16:09:42

How would you add the :key metadata to all elements of the seq with something like (interpose [:br] (string/split str #"\n"))? This is just for a temporary message, a random unique key would be good enough.

pesterhazy16:09:53

@l1sp3r looks like @carly is right, but I'm wondering why that is

pesterhazy16:09:48

if you reset! an atom to the same value, do the watches not fire?

carly16:09:25

They should not fire because, as far as I understand, it should compare and only fire if there is a difference in the atom.

noisesmith16:09:47

it’s because react knows to not re-render if the data has not changed, and :key helps it know the item moved in the list (maybe) but did not change

pesterhazy17:09:07

@noisesmith are you replying to me?

noisesmith17:09:09

the object identity of the item inside the atom is the first thing reagent checks, and then the next thing is value equality, the :key metadata tells it what to check, but even if the object identity is different and the values are equal it should not re-render

pesterhazy17:09:31

not sure I follow

pesterhazy17:09:59

my understanding is that reagent uses forceUpdate manually to trigger rerenders

pesterhazy17:09:09

it doesn't rely on props or this.state

pesterhazy17:09:36

so I'm not sure where a key would be relevant

pesterhazy17:09:03

@carly do you have a pointer to the source? I can't find the place in reagent where this check is done

noisesmith17:09:04

so if you start with [:div ^{:key :a} foo ^{:key :b} bar] and then switch to [:div ^{:key :a} foo ^{:key :c} baz ^{:key :b} bar] reagent knows to move bar, rather than re-rendering both baz and bar

rgdelato17:09:30

that is also the behavior in vanilla React

noisesmith17:09:33

because based on :key it knows which specific item in the list that was (despite th re-order)

pesterhazy17:09:17

that wasn't @l1sp3r's question though if I understood him - it was about re-renders triggered by resetting a ratom with the same value

l1sp3r17:09:46

@pesterhazy thats right, consensus appear that it doesn't caase a re-render

noisesmith17:09:47

that’s the other part of what I said: “the object identity of the item inside the atom is the first thing reagent checks, and then the next thing is value equality”

noisesmith17:09:59

oh - maybe I’m wrong on this…

noisesmith17:09:33

in general for atoms a watch triggers on reset! even if the values are equal

pesterhazy17:09:12

yup

=> (let [!x (atom {:counter 0}), _ (add-watch !x :test (fn [& args] (prn [:watch args])))] (swap! !x update :counter identity))
[:watch (:test #object [cljs.core.Atom {:val {:counter 0}}] {:counter 0} {:counter 0})]
{:counter 0}

pesterhazy17:09:40

which is a good thing, as otherwise the check would require a deep compare I think

pesterhazy17:09:18

so my theory is that assoc is smart about returning the same map if oldval==newval

pesterhazy17:09:21

(let [u {:counter 0} v (update u :counter identity)] (identical? u v))

pesterhazy17:09:30

which makes it true that after swap!ing an atom, oldval is still identical to newval

pesterhazy17:09:14

meaning that if the actual values don't change, the re-render is not triggered even though the ratom was dereffed

pesterhazy17:09:33

if that's true, quite a few things have to conspire for that to actually work

noisesmith17:09:31

here’s my figwheel repl:

(cmd)dev:cljs.user=> (def m (reagent.core/atom {:a 0}))
#'cljs.user/m
(ins)dev:cljs.user=> (def m0 @m)
#'cljs.user/m0
(ins)dev:cljs.user=> (swap! m update :a identity)
{:a 0}
(ins)dev:cljs.user=> (def m1 @m)
#'cljs.user/m1
(ins)dev:cljs.user=> (identical? m0 m1)
true

noisesmith17:09:42

now if you used reset! you won’t see that kind of result I bet

noisesmith17:09:38

(ins)dev:cljs.user=> (reset! m {:a 0})
{:a 0}
(ins)dev:cljs.user=> (def m2 @m)
#'cljs.user/m2
(ins)dev:cljs.user=> (= m1 m2)
true
(ins)dev:cljs.user=> (identical? m1 m2)
false

Jon18:09:28

I made my virtual DOM library even simpler to try:

Jon18:09:36

(def app
  (create-tiny-app->
    {:model store
     :updater updater
     :view comp-container
     :mount-target (.querySelector js/document ".app")
     :ssr? false
     :show-ops? true}))

(def reload! (:reload! app))

(set! (.-onload js/window) (:start-app! app))