This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-07-13
Channels
- # aleph (5)
- # beginners (92)
- # cider (37)
- # cljs-dev (38)
- # cljsjs (2)
- # cljsrn (3)
- # clojure (50)
- # clojure-berlin (1)
- # clojure-canada (3)
- # clojure-dusseldorf (4)
- # clojure-france (1)
- # clojure-germany (1)
- # clojure-italy (7)
- # clojure-nl (21)
- # clojure-spec (2)
- # clojure-uk (106)
- # clojurescript (165)
- # code-reviews (1)
- # community-development (3)
- # cursive (5)
- # datomic (13)
- # editors (12)
- # emacs (3)
- # figwheel-main (141)
- # fulcro (28)
- # graphql (1)
- # immutant (1)
- # jobs (1)
- # jobs-discuss (5)
- # midje (8)
- # nrepl (3)
- # off-topic (28)
- # onyx (4)
- # re-frame (21)
- # reagent (70)
- # ring (2)
- # ring-swagger (9)
- # shadow-cljs (18)
- # spacemacs (6)
- # specter (23)
- # tools-deps (21)
does reagent start re-renders synchronously on when a ratom
has been changed? it looks like it does but i can’t think of how to do an experiment to confirm
and by “re-renders” i mean on the reagent side. i realize on the react side it batches
@lee.justin.m don’t no how to experiment it either, but think it is batched/async
So I believe the reactions are added as watchers on the ratom
. The way a reaction reacts to a change notification is by registering itself “dirty” and being placed on a queue
well actually i think this is a test, which indicates that it is batched:
(def test-atom (reagent/atom "foo"))
(defn a-component
[]
(print "a-component")
[:div @test-atom])
(defn test-component
[]
(print "test-component rendering")
[a-component])
(js/setTimeout
(fn []
(print "Pre reset")
(reset! test-atom "bar")
(print "Post reset"))
0)
=>
test-component rendering
a-component
Pre reset
Post reset
a-component
i am getting side effects happening in my program in between pre and post and i don’t understand why and now i can see the re-framers saying I told you so 🙂
@lee.justin.m Haven't checked the implementation, but I recall reading that it's either an reagent or re-frame feature to do updates only when RAF hits
So if there are quick enough updates, some will not ever be visible even in the virtual dom
i know for sure that reagent batches react updates in a raf, but the question i had is when does the reagent cycle run with respect to atom mutations
something in my code is causing the reagent renders to happen synchronously. i don’t really understand why that’s happening.
Hm. I know it's a bit odd place to look for it, but if the reagent docs don't comment on that (and they are pretty sparse), it might be explained in re-frame docs
They seem to give credit where it's due, and IIRC re-frame subs are also async and batched
that code is beyond my skill level. there’s a reason why we can’t get anybody to volunteer to document the reactions/tracking functions 🙂
@lee.justin.m I’m curious though, what happened to the original author of these things? I don’t know that I see a presence of them around the slack channel, and not sure on GitHub either.
@U0LK1552A I’m just as curious! Dan Holmsand or something like that appeared to have written everything and then he just dropped off the map as far as I can tell. It’s really interesting how these things happen.
When I did the documentation project I was really frustrated because it would have been awesome to have someone to just explain the thought process. He did SO MUCH WORK on the project including awesome documentation I’m a bit surprised that he’s totally checked out.
I think Juho stepped in at some point. He’s kind of a wizard. I have wanted to start helping with maintenance but I think I would need someone to really help me figure out WTF some of this stuff is. I understand a lot of reagent now but I still run into things that just baffle me (like how the react component caching works)
well thanks for the info, I knew you did work on the docs etc and I was following along, but was confused why the main author has never chipped in before - and now I know it is a mystery
This is a little scary. I have been thinking about doing a blog series on various reactive hacks out there. And as we speak I am trying to conjure up an example that will test if ratoms are susceptible to glitches.
One of these days I’m going to try to go through the impl enough to doc some of it. I’ve followed through it before and generally can understand it. But yeah. Need a deep understanding to find edge cases.
Some of the trickiest parts is how different reactive objects hold links to each other. And how there are various caching mechanisms they use for apparent performance gains.
I am going to take a peek at the code now, I am curious what mechanism might be in use. Some libs use transactions, MobX uses mark-and-sweep. I am an outlier, I use an integer “pulse”.
Yeah you have some background in various techniques. May be good for gaining insights.
Damn, that code looks familiar. I always, say, the problem determines the solution.
I got excited when I saw ratomGeneration thinking it was my pulse
but it seems to be just for dev/debug.
“apparent performance gains” Yes, depending on the application, caching can be indispensable to the paradigm performance-wise.
In effect, the caching is what makes what I like to call functional state feasible. When we stumbled onto dataflow we just wanted functional state, but we were doing complex GUI layout computations so performance forced us to track dependencies so we could propagate intelligently and minimize computation. We never meant to do dataflow, it just forced itself on us. 🙂
OK, yes, Reagent is susceptible to glitches, meaning with just the right set up of ratoms a change to one will propagate twice to a ratom, with the first calculation being inconsistent with the original change. I imagine re-frame inherits this edge case.
Could be wrong too. Well I guess app state is in a ratom actually. Will have to look around
(def xx (r/atom 0))
(declare bb)
(def zz (r/track! #(let [r (if (> @xx 3)
(+ @xx @bb)
@xx)]
(prn :zz r)
r)))
(def aa (r/track! #(do (prn :aa)
(* 10 @xx))))
(def bb (r/track! #(do (prn :bb)
(* 10 @aa))))
Now increment xx
until it gets to 4 and you will see zz
take on first 304 and then 404.
Changing xx
marks zz
and aa
as dirty, but does not mark bb
as dirty. xx
notifies zz
first and it runs and gets a now obsolete copy of bb
. xx
then notifies aa
who notifies bb
who then re-notifies zz
.
xx
cannot be sure bb
is dirty because aa
might not change. MobX has two dirty states, definitely and possibly, which here would be applied to aa
and bb
.
The trick MobX and my hack both use is to make one last check when deref-ing that the value being grabbed is current.
btw, having the dependency on bb
conditional is not (I think!) necessary to expose the glitch. It is there just to defeat naive solutions as “check all your dependencies before running”. Since zz
does not yet know it will branch to a read of bb
that will not surface the problem. That is why MobX and I check for currency as the actual read of any ratom is executing.
And regarding #re-frame, using reg-sub
for zz
would mean listing bb
in the signals, because it might be needed. This avoids the glitch at the expense of recomputing zz
unnecessarily when bb
changes and xx
is <= 3. So reg-sub-raw
is misnomer; reg-sub
is not syntactic sugar, it is a different animal.
I’ve done repl-time modifications in it before to gather more contextual info before to troubleshoot things
@lee.justin.m As a long-time reactionary I can tell you that (a) it is wonderful something-for-nothing magic but (b) if you exercise it hard enough you will run into what we can call (nom du jeur) “lifecycle”. As in, “Jeez, when does this fire?” I just did some experiments with re-frame (yes, experiments are a great way to sort these things out) and what I saw was that re-frame is too simplistic to get into much confusion, at the cost of over-propagation. (But that over-propagation is rarely a problem in practice.) I stopped experimenting before I got to reagent but if you would like to share your use case I will be happy to take a look. If you are really curious about the paradigm, scroll down to “data integrity” here to see the guarantees we need for reactive software: http://smuglispweeny.blogspot.com/2008/02/cells-manifesto.html
thanks @hiskennyness. i actually figured out the problem. I was seeing concurrent networks calls and wondering how it was happening. it was happening because… I was making concurrent network calls lol
but reagent does not ever appear to cause re-renders on state changes synchronously, which is a good thing
OMG! Concurrent network calls are the last thing I worry about when I am making concurrent….hang on…
Glad to hear your world is right again, God is in his heaven, and all that…
OK, yes, Reagent is susceptible to glitches, meaning with just the right set up of ratoms a change to one will propagate twice to a ratom, with the first calculation being inconsistent with the original change. I imagine re-frame inherits this edge case.
And regarding #re-frame, using reg-sub
for zz
would mean listing bb
in the signals, because it might be needed. This avoids the glitch at the expense of recomputing zz
unnecessarily when bb
changes and xx
is <= 3. So reg-sub-raw
is misnomer; reg-sub
is not syntactic sugar, it is a different animal.