This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
- # 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)
@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
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.
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
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.
I was trying to follow something like this: https://github.com/Day8/re-frame/blob/master/docs/Subscribing-To-External-Data.md#some-code
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.
Perhaps have a read of this: https://github.com/Day8/re-frame/blob/master/docs/FAQs/PollADatabaseEvery60.md
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
@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
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
Oh... duh. There's an event that changes
:credentials which should just issue another event to re-create the client.
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.
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?