This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-05-04
Channels
- # admin-announcements (9)
- # beginners (40)
- # boot (61)
- # cider (6)
- # cljsrn (5)
- # clojure (65)
- # clojure-gamedev (6)
- # clojure-greece (8)
- # clojure-ireland (1)
- # clojure-portugal (5)
- # clojure-russia (46)
- # clojure-uk (38)
- # clojurescript (177)
- # core-async (9)
- # cursive (17)
- # datomic (6)
- # dirac (8)
- # emacs (5)
- # error-message-catalog (8)
- # hoplon (248)
- # ldnclj (11)
- # ldnproclodo (1)
- # lein-figwheel (36)
- # leiningen (12)
- # mount (2)
- # off-topic (3)
- # om (26)
- # onyx (12)
- # perun (2)
- # planck (26)
- # re-frame (62)
- # reagent (55)
- # remote-jobs (2)
- # rethinkdb (1)
- # ring-swagger (14)
- # spacemacs (47)
- # untangled (69)
I am trying to understand how atoms
and reactions
work. In the readme for re-frame, I read that (in section How Flow Happens in Reagent), "The magic thing about a reaction is that the computation it wraps will be automatically re-run whenever 'its inputs' change, producing a new output (return) value."
(require '[reagent.core :as r])
(require-macros '[reagent.ratom :refer [reaction]])
(def app-db (r/atom {:a 1}))
(def ratom2 (reaction
(do
(println "running")
{:b (:a @app-db)})))
That's exactly the way it should be
Reagent just rerun reactions when ratoms they deref
change
the "input" is the deref
of an ratom
@hugobessaa: thanks. what I am seeing is that when I perform a reset!
on app-db (as in the readme), the ratom2
doesn’t get updated till I deref it.
reagent uses this as a performance improvement. if you do not deref a ratom, it means you're not interested in it's value and so do not recompute it.
@hugobessaa: that makes sense to me. but i am struggling to figure out why the readme of re-frame suggests automatic computation..
> Well, the computation is just a block of code, and if that code dereferences one or more ratoms, it will be automatically re-run (recomputing a new return value) whenever any of these dereferenced ratoms change.
this paragraph makes it very clear that re computations are done when you deref
a ratom. you think it could be more explicit?
@hugobessaa: thanks. i think my confusion arises from the fact that in this context, which ratom being deref
ed would cause the computation to happen. so its the deref of the ratom returned from the reaction.
@roberto: atleast in my example, if i deref the ratom2
, 2 times, i see ”running”
printed twice suggesting to me that code is run twice.
yeah, I ask because sometimes I deref the same atom at the same time in multiple locations
I appreciate re-frame’s docs, but I also have issues understanding ratom once I start building an app that needs to deref the same ratom in multiple locations.
@roberto: agreed. my unscientific and uneducated hunch is that the real power of the ratom
is only realised when used inside a component
or inside a reaction
. something that is even less documented
the reagent
readme just gives an overview of it's power and functionality
I'm starting to realize we should help reagent to document better it things.
A nice thing to do after the 0.6.0
release that is closeby
@hugobessaa: agreed.
@fasiha: i think it returns something which is essentially the same thing as ratom
in the sense that it implements all the same protocols as ratom
(and more)
Suppose I have a Type-II re-frame component, something like:
(defn my-component []
(let [reaction-1 (subscribe [:sub1])
reaction-2 (subscribe [:sub2])]
(fn [] [:div @reaction-1 @reaction-2])))
and say reaction-1
is always getting updated because the sub1
subscription returns a frequently-changing piece of app-db, but reaction-2
and sub2
change very infrequently. Am I correct in understanding that when my component gets re-rendered because of a change in reaction-1
, the subscription to sub2
will NOT get called—or if it is called, the subscription function will notice that that piece of app-db hasn't changed since last time and will not run the reaction?The type II component creates these reaction
s from subscribe
when the component is created to be rendered (the first time probably)
I have a fancy sub2
, i.e., a reaction-inside-a-reaction:
(re-frame/register-sub
:sub2
(fn [db]
(let [parameter-reaction (reaction (:path @db))]
(reaction (EXPENSIVE-FUNCTION @parameter-reaction)))))
it's important to note that the reaction
holds the value from a computation
it do not run the computation once per deref
it run when creating with the (reaction)
macro and when a ratom you deref
inside it changes
Ahh, that's much clearer, thanks @hugobessaa !
actually I'm not even sure if the (reaction)
executes it's computation when it is created
maybe just when you deref
it for the first time. but I'm not sure
So what happens if my subscription creates a first reaction
, then derefs it not in another reaction, and then returns a second reaction?
I.e.,
(let [reaction-1 (reaction (:path @db))
first-value (first @reaction-1)]
(reaction (inc first-value)))
first-value
will get a "cached" copy of (:path db)
if it's not changed, and the rest is as normal?
fasiha, I got bad news for a reaction with expensive computation
I tested a reaction inside the REPL
it will run the computation everytime it is deref
ed
ok, so I did more testing inside the REPL
answering your first question: it will run the computation of a reaction everytime it is deref
ed
answering your last question: a reaction without a deref
inside will return the same value everytime you deref
it
test that in a REPL
you could write the last code as:
(let [reaction-1 (reaction (:path @db))
first-value (reaction (first @reaction-1))]
(reaction (inc @first-value)))
so the returned reaction would work as expected
these tests remembers me I need to dig deeper into the inner workings of reaction
and r/atom
Thanks for the explanation @hugobessaa that's definitely helpful. I do need to internalize the rules about when things get rerun thru experimentation—usually just "knowing" the rules isn't enough
@rohit: the readme was not intended as a tight specification document, it was mostly about giving mental models:
https://www.reddit.com/r/Clojure/comments/4h1fv4/a_technical_overview_of_arachne/d2s0a6w
And if you are using 0.6.0, remember also that Dan has done recent work on reaction
, so I'm not sure where we are currently around this, except to say it has changed with this release.
Anyone checked out https://github.com/mobxjs/mobx? It brings mutability back into the mix but it's pretty interesting. Seems like fewer moving parts and easier to get started with than redux, et al. The way the observable state is wired up might be an interesting alternative to manual subscriptions in re-frame