Fork me on GitHub
#re-frame
<
2018-08-24
>
jeaye05:08:03

Is there a good way of intercepting every dispatch to tack on some data (or metadata)? I'm thinking of tying each event I dispatch to the current user id and wrapping my own reg-event-db and reg-event-fx to ensure the event is handled only if the user id still matches. I've been seeing a few manifestations of the same issue: the user logs out and various things (from :dispatch-later to HTTP responses to Firebase callbacks) end up triggering, for the first user, when I log in as a new user.

jeaye05:08:21

I could just use my own dispatch, but then I need to worry about accidentally using re-frame's. I'm hoping there's a more supported way, but I haven't found anything in the docs or issues for it. Seems like I need to either define my own wrapper dispatch or redefine re-frame's.

lwhorton17:08:58

the reframe core is rather approachable. you could also just write your own dispatcher fn and ignore the internals. that dispatcher handles metadata collection, then calls reframe/dispatch. imo you should always be using {your-domain}.re_frame namespace as a lib wrapper anyhow, for reasons like this (and others).

gadfly36105:08:43

@jeaye I think the recommended way of intercepting every dispatch would be something like this: https://github.com/Day8/re-frame/blob/master/docs/FAQs/GlobalInterceptors.md

mikethompson07:08:35

@jeaye @gadfly361 or create a function called emit which does what you need to the event argument, then calls dispatch

mikethompson07:08:50

And then you use emit everywhere

mikethompson07:08:56

Perhaps you'd also need to write your own effect handler for :emit (instead of :dispatch). Maybe.

iperdomo08:08:30

Hi again, a friendly bump of my question: What's the best way to deal with async API call and coeffects? I'm trying to write something similar to https://github.com/gothinkster/clojurescript-reframe-realworld-example-app/blob/master/src/conduit/db.cljs#L44-L50 ... in this code, getting a logged user from localStorage involves a synchronous api call, we can just assoc ... In my case, I'm trying to get a user session via AWS Cognito JS SDK, that is async ... https://docs.aws.amazon.com/cognito/latest/developerguide/using-amazon-cognito-user-identity-pools-javascript-examples.html#using-amazon-cognito-identity-user-pools-javascript-example-retrieving-current-user

iperdomo08:08:17

my understanding is that the interceptor will be executed before a handler is called, but the AWS Cognito code will set the value async, via a callback, since it also attempts to refresh the session if the token is invalid (an HTTP call to a service) ... could it be the case that my handler code gets executed without a session because the callback has not been called?

zalky12:08:21

@U0GTGHX1D: Not having used the AWS Cognito JS SDK myself, your concern is nevertheless valid. The entire event chain is processed synchronously so the callback may not have had a chance to be called. Rather than co-effects, a general approach for callbacks might be: Event #1 produces an effect that creates the callback (ie: .getSession). In the callback, dispatch event #2 with whatever data is available in the callback context. So specifically, something like:

(f/disaptch [:with-user [:event arg1 arg2]])

(f/reg-fx :with-user
  (fn [event]
    (.getSession user-pool
                 (fn [err session]
                   ... (f/dispatch (conj event session))))))

(f/reg-event-fx :with-user
  (fn [_ [_ event]]
    {:with-user event}))

(f/reg-event-fx :event
  (fn [_ [_ arg1 arg2 session]]
    ...))
Just one approach, there may be others.

iperdomo13:08:01

@U0HJK8682 thanks for the reply, I think I'll follow this approach

danielneal10:08:22

does anyone have a way of adding docs to reframe events/subs etc?

lwhorton17:08:36

use the built in defn doc string

lwhorton17:08:00

(reg-sub :sub my-sub)
(defn my-sub "doc string" [db] ...)