This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-09-29
Channels
- # beginners (10)
- # cider (10)
- # cljs-dev (17)
- # clojure (14)
- # clojure-losangeles (1)
- # clojure-spec (1)
- # clojure-uk (3)
- # clojurescript (49)
- # core-async (5)
- # css (1)
- # datomic (2)
- # duct (26)
- # emacs (13)
- # figwheel (6)
- # figwheel-main (5)
- # garden (1)
- # keechma (6)
- # nrepl (1)
- # off-topic (6)
- # re-frame (52)
- # shadow-cljs (132)
- # spacemacs (4)
- # tools-deps (26)
What do you mean credentials federation? @ghopper
@drewverlee, I take Google openid credentials after a user logs in and do a federated sign in to AWS to get a temporary access token. That's not really the relevant part here though.
I think I've come up with a solution, though it still feels like I'm doing something wrong. Some feedback on the name of this function would be great. 🙂
(defn make-value-reaction [f]
(let [a (r/atom nil)
reaction (ratom/make-reaction #(f a))]
@reaction
(ratom/make-reaction
(fn [] @a)
:on-dispose #(ratom/dispose! reaction))))
(rf/reg-sub-raw
:example
(fn [_]
(make-value-reaction
(fn [a]
(let [sometimes-nil @(rf/subscribe [:sometimes-nil])]
(if sometimes-nil
(reset! a (make-thing-when-not-nil sometimes-nil))
(reset! a nil)))))))
What's happening here is that I want to have a subscription that always returns the same instance no matter how many times it's referenced and gets updated only when [:sometimes-nil]
is changed.
I think the only way to do this is with the two reaction thing. Otherwise I end up with a cascade where a reaction causes itself to update continually.
Also, this lets me handle async functions which return nil
at first until they have data:
(rf/reg-sub-raw
:value
(fn [_]
(make-value-reaction
(fn [a]
(let [example @(rf/subscribe [:example])]
(when example
(.then (.getData example)
#(reset! a (js->clj %)))))))))
@ghopper this may all fall out rather easily if you treat a promise the same way you treat an HTTP request
That approach assumes you will store the results of the HTTP (or promise) in app-db
really? i thought the library handed back a parsed body and you could do with that what you wanted, why does it need to be put into the db.
@drewverlee
Seems a reasonably likely outcome to assume.
An event is dispatched with the HTTP result. The associated event handler (which processes that event containing the result) will likely put some aspect of that result into app-db
. Other paths are possible, but unlikely.
So my point is: the outcome of a promise
can be processed in the same way as the outcome of an HTTP GET
.
Oh yeah, I see. Just making sure I didn't miss something
And the subscriptions simply deliver that through to the views
The struggle you have at the moment is that your subscriptions are doing too much
Oh, that makes sense. I wasn't thinking the result of this could be put in the db
via a second dispatch.
yeah, the then
of the promise just does a dispatch
I was trying to follow something like this: https://github.com/Day8/re-frame/blob/master/docs/Subscribing-To-External-Data.md#some-code
The same as the on-success
of the HTTP request
Where the act of subscribing set up and tore down the request. (Eventually there will be a websocket connection as well.)
Yeah, if I had time, I'd redo that documentation or possibly remove it. It was more of an experiment to document that process (which has a few moving parts). There are some caveats at the bottom.
websockets just dispatch
when something arrives
The arrival is an event in the same way as a user clicking on something
What would you use to start and end that websocket connection?
An effect handler
Anthing that mutates the world (starts and ends websockets) is an effect
Perhaps have a read of this: https://github.com/Day8/re-frame/blob/master/docs/FAQs/PollADatabaseEvery60.md
That would need to be called by an event, right?
Thanks
Ah, it looks like this is what I'm looking for. :thumbsup:
Yes, your re-frame system is event driven. Nothing happens unless there is an event. So websocket only gets opened because of some event or other. So it will be the event handler which knows to now open the websocket. And it will produce an effect
So, should I have that event triggered inside a React lifecycle method, if I want the websocket connected while the component is visible?
No, now you need to read another FAQ: :-) https://github.com/Day8/re-frame/blob/master/docs/FAQs/LoadOnMount.md
Heh, clearly I've missed a lot of these. 😛
Also be sure to read the link in that FAQ to http://PurelyFunctional.tv
Thanks
@mikethompson, so I have a client
, which needs to always be re-created whenever credentials
changes. This client
should be in db
, so I can easily pull it out for rf/reg-fx
, right? How should I go about keeping it updated whenever (rf/subscribe [:credentials])
changes? (`:credentials` is also stored in the db
.)
Up until now, I've been using the fact that re-frame deduplicates subscriptions to my advantage, though I have to then pass the client
through the (rf/dispatch)
which passes it on to the effects that need it.
(Meaning, I just have a subscription that uses [:credentials]
as an input and returns a new client
.
Oh... duh. There's an event that changes :credentials
which should just issue another event to re-create the client.
I think it's all starting to click for me. 😉
Yeah, remember that re-frame is event driven. It is events which move the system from one state to another. Every event cause some "change": a change to app-db
or opening a web socket. These are the effects.
subscriptions simply deliver data
They are not imperative
They do not cause things to happen
(only events cause things to happen, and even then ... only via effects)
It's starting to make sense. 🙂 Thanks for your patience.
So if I were to have a subscription that pulls some derived data out of the database (the sum of multiple items or something), and I were to need that value inside an effect handler, I would have to create a new function, that accepts the db, for the subscription handler and the effect handler to use, right?
@ghopper yeah, I think that sounds right
The value could be also be computed and cached in app-db
If multiple parts of the system need it.
Maybe.
Ah, good point. I hadn't thought about caching it.