This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-01-10
Channels
- # adventofcode (3)
- # aws (2)
- # beginners (85)
- # boot (8)
- # boot-dev (4)
- # cider (36)
- # clara (3)
- # cljs-dev (87)
- # cljsrn (3)
- # clojure (87)
- # clojure-austin (12)
- # clojure-brasil (1)
- # clojure-dev (8)
- # clojure-dusseldorf (5)
- # clojure-estonia (5)
- # clojure-greece (4)
- # clojure-italy (3)
- # clojure-spec (17)
- # clojure-uk (55)
- # clojurescript (70)
- # core-logic (2)
- # cursive (6)
- # data-science (18)
- # datomic (13)
- # emacs (34)
- # fulcro (347)
- # graphql (12)
- # hoplon (6)
- # jobs (3)
- # jobs-discuss (43)
- # juxt (2)
- # keechma (31)
- # leiningen (29)
- # lumo (2)
- # midje (2)
- # off-topic (118)
- # om-next (4)
- # onyx (39)
- # pedestal (6)
- # re-frame (85)
- # reagent (21)
- # remote-jobs (3)
- # ring (5)
- # rum (2)
- # shadow-cljs (126)
- # spacemacs (1)
- # sql (6)
Why is the re-frame db not passed to the extractor fn of a subscription defined with an extractor fn and a computation fn?
@kenny
I'm assuming you mean signal fn
instead of extractor fn
.
If so, to answer your question: (1) it generally isn't needed (2) if it is then do this:
(reg-sub
:db
(fn [db] db))
which would allow you to then use (subscribe [:db])
within the signal fn
of whatever further subscription needs to get to all of db
AND, presumably, something else. But you'd need to be doing something, er, exotic to need it.@mikethompson No I meant extractor fn. If I have a subscription defined like this:
(rf/reg-sub
:my-sub
(fn [arg1 arg2]
(println (pr-str arg1 arg2))
"abc")
(fn [s]
(str s "d")))
arg1
is the query-vec [:my-sub]
and arg2
is nil
.(fn [arg1 arg2] ...)
is known as the signal function
I just did a hasty search and couldn't find that reference
Ahh, non written
I'll correct, sorry
But my comments above stand
Have a bit of a look through https://github.com/Day8/re-frame/blob/master/examples/todomvc/src/todomvc/subs.cljs
You generally have multiple layer 2
subscriptions. They are made trivial.
They just "extract"
Then further computation is done in layer 3
The Layer 2's just want access to db
. Nothing else
The Layer 3's will take layer 2s as input (one or more)
Layer 3 DO NOT want direct access to db
Because they don't want to re-run each time app-db changes
The purpose of this arrangement is efficiency.
My use-case is a bit, in your words, exotic. Example:
(rf/reg-sub
::example
(fn [db _]
(do-query my-query (:selected db)))
(fn [query-result]
(sort query-result)))
do-query
returns an ratom which I'd like to use as the input to the computation.do-query
queries a remove database?
Yes, I have looked at existing libs that do this and they are not solving the same problem.
I believe this would work:
(rf/reg-sub
::selected
(fn [db _]
(:selected db)))
(rf/reg-sub-raw
::example2
(fn [db _]
(ratom/reaction @(do-query my-query (:db @db) @(rf/subscribe [::selected])))))
(rf/reg-sub
::example2-sorted
:<- [::example2]
(fn [query-result]
(sort query-result)))
I don't think I'm fully following the signal graph, but you can use the rarely seen double-deref @@
to possibly simplify some code here
Just wondering if you can remove ::example-2 and @@ on do-query
Unless you want it to be a separate subscription to use elsewhere
no, same thing
I think what I'm after is a function that allows you to create all of your input signals given the DB and still attach a computation.
kinda like half-way between reg-sub-raw and reg-sub?
Something like this?
(reg-inputs-sub
:<- [::selected]
(fn [db [selected] query-v]
(do-query my-query (:db db) selected))
(fn [query-result]
(sort query-result)))
oh, a three level thing
You could have do-query
just return the reaction in one sub, and then you deref it in the next
(rf/reg-sub
::selected
(fn [db _]
(:selected db)))
(rf/reg-sub
::db
(fn [db _]
(:db db)))
(rf/reg-sub
::example2
:<- [::selected]
:<- [::db]
(fn [[selected db] _]
(do-query my-query db selected)))
(rf/reg-sub
::example2-sorted
:<- [::example2]
(fn [query-result]
(sort @query-result)))
does that work?
Is there a reason re-frame forces the creation of ::example2
and ::example2-sorted
? If I only ever care about the latter, why should I need to create two subscriptions for it?
Wait a minute, I don't think your example will work. do-query
returns a ratom, not a value.
You might be interested in: https://github.com/Day8/re-frame/blob/master/docs/Subscribing-To-External-Data.md
But note the reservations towards the bottom
"The Alternative Approach"
and "Absolutely Never Do This"
I think it will still work, because computation-fn
is still run inside a make-reaction
The reg-sub
function does the dereffing of subscriptions for you so you don't need to think about it, but derefing a subscriptions (reactive) value is also going to happen inside the same reaction context, so should be fine too
I think that link is mostly geared around actually external data. What I'm suggesting is being able to functionally create the input signals to a subscription. Hmm, I'll try it. My understanding was that the computation-fn needed to return a value, not a ratom.
It does if you want to be able to use it in other reg-subs without having to deref it, but it's just a convention to avoid mistakes
(make-reaction
(fn []
(computation-fn (deref-input-signals subscriptions query-id) query-vec)))
If you computation fn returns a value then it will be wrapped in a reaction which everything else expects
by convention you'd want everything to be taking and returning values for simplicity
but if you do your bookkeeping carefully and are aware that you're returning a reaction that returns a reaction, then you can do what I showed above
So that works without throwing an exception except that ::example2
does not get updated when the do-query
ratom changes.
Great! gtg, can discuss more tomorrow your time
Did you have a specific question about it? I’ve heard of it being used a few times before.
Also, there is https://github.com/gadfly361/soda-ash which is a cljs wrapper layer that may or may not be something valuable to you in using it
Just double checking, if I run (do (dispatch [:a]) (dispatch [:b]))
Then :a
will always complete before :b
is processed?
I believe that is what I referenced to give myself confidence that that is a valid assumption
@cmal Slightly late to this, but we have used vega which is a layer over D3 for charting. It is has gone well for us. Depends what charting you want to do. A bit of a learning curve for vega, mind you there's a pretty decent learning curve with D3 itself, too. Vega-Lite is easier.
using re-frame-test and karma and it all works great locally … wondering if it runs headless?