This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-05-03
Channels
- # aleph (7)
- # announcements (6)
- # babashka (34)
- # beginners (5)
- # calva (1)
- # cider (3)
- # clerk (11)
- # clj-http (1)
- # clj-kondo (35)
- # clojars (6)
- # clojure (114)
- # clojure-australia (1)
- # clojure-brasil (2)
- # clojure-europe (73)
- # clojure-hamburg (3)
- # clojure-nl (1)
- # clojure-norway (27)
- # clojure-uk (4)
- # events (3)
- # graalvm (13)
- # gratitude (4)
- # helix (17)
- # hoplon (1)
- # hyperfiddle (65)
- # instaparse (4)
- # jobs-discuss (6)
- # lsp (2)
- # meander (2)
- # rdf (4)
- # re-frame (51)
- # reitit (28)
- # releases (1)
- # sci (20)
- # shadow-cljs (9)
- # tools-deps (4)
- # xtdb (44)
Async != unordered. Order matters when effects depend on each other, implicitly or explicitly.
The most obvious one is :db
and :dispatch
where the handler of the dispatched event expects for some value to already be in the app-db.
Another example is where you have a :dispatch
effect that changes app-db and e.g. some HTTP effect that relies on that change.
In other words, preserving effect order allows for simpler composition.
The effects aren't scheduled, they are executed immediately, right after a particular event is handled.
no not the effect, the event you :dispatch via :fx to update app-db will be scheduled
then the loop will continue to the next effect in the vec while the :dispatch is happening
Re-frame preserves that order. Whether it's important or not depends more on the application itself.
The queue processing does not allow for interim renders unless you flush the DOM with Reagent. So regardless of the order, the views will see app-db changes only once the queue is empty again.
if we dispatch multiple stuff at the same time, theri call order will determine their order in the queue
Hi, I am trying to understand how I could use subscriptions that depend on each other. Like the signal graph documentation. However my problem is that I have multiple async actions that depend on each other. I have the following code:
(rf/reg-sub-raw :authentication-doc-id
(fn [db]
(-> (fire/call-function "clientLoginBankID" {:interface :admin})
(.then #(rf/dispatch [:authentication-doc-id-updated (.-data %)]))
(.catch #(rf/dispatch [:authentication-doc-updated %])))
(ratom/make-reaction
(fn [] (get-in @db [:login :authentication-doc-id]))
:on-dispose (fn []
(rf/dispatch [:authentication-doc-id-updated nil])))))
(rf/reg-sub-raw :authentication-doc
(fn [db [_]]
(let [authentication-doc-id @(rf/subscribe [:authentication-doc-id])
unsubscribe
(when (not (nil? authentication-doc-id))
(js/console.log (str "Subscribing to authentication-doc " authentication-doc-id))
(-> (fire/db)
(fire/col "authentication")
(fire/doc authentication-doc-id)
(fire/sub
(util/doc-snap #(rf/dispatch [:authentication-doc-updated %]))
(util/on-error #(rf/dispatch [:authentication-doc-updated %])))))]
(ratom/make-reaction
(fn [] (-> @db :login :authentication-doc))
:on-dispose (fn []
(when unsubscribe
(unsubscribe)))))))
Where :authentication-doc should subscribe to a Firestore document with the ID given by the :authentication-doc-id subscription. This code does not work properly and I can't find examples that use nestled async subscriptions.
Any pointers?There is no such thing as async subscriptions. I'd suggest moving all impure things, all the "doing", into events. And make the subs do what they're designed to be doing - fetching and transforming data from app-db.
Ok, I'm not sure when I should create the async operations. As far as I understand the events should be dispatched when the async operation is finished? (Sorry if I'm asking stupid questions. I'm new to re-frame)
Stupid questions are alright, but unless you have already read all of re-frame documentation, you should definitely do it.
Any async operation is not different from e.g. the existing :http-xhrio
effect or any other similar thing.
You initiate some async workflow with an effect returned from an event handler. That effect handler receives some "continuation" events that it will dispatch in .then
or using whatever async functionality you've got.
Yes, I read it multiple times. It contains some new concepts that I'm trying to keep structured in my head. Ok, but those effects does not get triggered by a subscription? I thought it was quite a beautiful solution in my views just to subscribe to data and it will appear once the data is stored in the app-db.
So this solution is not recomended? https://github.com/day8/re-frame/blob/master/docs/Subscribing-To-External-Data.md#some-code
Not recommended indeed - see the very start of that file, with "This document will soon be retired". It might be a beautiful solution but only superficially. It has its downsides and you have stumbled upon one of them.
yes, but the thread refered to at the top wasn't really solving my problem
oh, sorry
I was confusing it with dynamic subscriptions
I have missed those pointers. Will read. Thanks!
Also keep in mind that global interceptors exist. They make it handy to monitor a particular property value without you having to alter every single event handler that touches the value.
Allright, haven't really dabbled with interceptors yet
But I'll keep it in mind
I need to use
(. js/navigator -userAgent)
and
(.. js/window -location -href)
Is it OK to use them in a subscription?Instead of the location.href, why not use reitit.frontend.easy/replace-state
or push-state
I do when I want to navigate. But i need this in order to send a back link to external app
or would that mess up purity?
In an SPA, the second value can change without refreshing everything. If you use that value directly in a sub, that sub won't trigger a re-render of anything.
you are right, however the value is combined with another value, so i suppose that it will be updated anyway. However, I thought that I should keep it in app-db, updating it along with the router event.