Fork me on GitHub
#re-frame
<
2022-09-06
>
popeye11:09:06

What is the difference between using :fx and :dispatch-n ?

{:fx [[:dispatch [:event1]]
      [:dispatch [:event2]]]}


{:dispatch-n [[event1]
               [event2]]}

Luke Zeitlin11:09:31

:fx is for any effects (including dispatching other events, but also your own custom effects): https://github.com/day8/re-frame/blob/master/docs/Effects.md

Luke Zeitlin11:09:46

using fx rather than dispatch-n is preferred according to API docs: https://day8.github.io/re-frame/api-builtin-effects/

popeye12:09:00

oh thanks for the reply šŸ™‚

Aspirational13:09:45

Hi guys! Do we have a workaround now for calling a subscription just once and not keeping it in the cache?

p-himik13:09:24

If you call it in a reactive context, it will be removed from the cache right when the view is unmounted.

Aspirational13:09:09

and what about the not-reactive context?

p-himik13:09:23

You can write your own version of subscribe that uses private but simple API of re-frame.

šŸ™Œ 1
āœ… 1
popeye13:09:03

I wrote below code , and I am not getting why event dispatch1 is not calling after called with dispatch-sync ! , and I am getting the error no handler registered for effect: , but this works if I define it in :dispatch , any reason ?

(reg-event-db
  :dispatch1
  (fn [db [_ resp]]
    (println "----2----")
    ))

(reg-event-fx
  :event1
  (fn [db [_ resp]]
    (println "------1----")
    {:dispatch-sync [:dispatch1 resp] }))

p-himik13:09:22

> no handler registered for effect I assume it's followed by :dispatch-sync? dispatch-sync exists in re-frame itself as a function. But it doesn't exist there as an effect.

popeye13:09:29

@U2FRKM4TW thanks for responding! Do you mean the way I am calling :dispatch1 is not right ?

p-himik13:09:20

I mean that the effect :dispatch-sync simply does not exist.

p-himik14:09:08

But :dispatch does exist - that's why it works.

popeye14:09:53

it is the namespace re-frame.core right ?

p-himik14:09:43

Nope. Effects and functions are completely different things. The fact that there's a function re-frame.core/dispatch and the fact that there's an effect :dispatch registered in re-frame.fx are completely unrelated. There's also a :dispatch-later effect, but there's no dispatch-later function.

popeye14:09:36

ohh ok, what if I have the scenario, where one of my event is depends on another, How can I achieve it ?

popeye14:09:50

shoud I use interceptor with after effect?

p-himik14:09:17

Depends on what you mean by "depends". :) Ideally, you would just refactor your code in such a way so that dependent functionality is tied together by composing functions.

popeye16:09:01

I am learning interceptor and wrote below code , when the after returns (assoc-in context [:effects :db] new-db) it does not giving expected result where as if I return context it is working as expected! What am I doing wrong ?

(def trim-event
  (re-frame.core/->interceptor
    :id      :trim-event
    :after  (fn [context]
              (let [{:keys [db ]} (:coeffects context)
                    new-db (assoc db :J "J")
                    _ (println "----E---"(keys (:effects context))"   "(keys (:coeffects context)))]
                (assoc-in context [:effects :db] new-db)))))

(reg-event-db
  :even1
  [trim-event]
  (fn [db [_ resp]]
    (println "------1----")
    (-> db
        (assoc-in :t "t")
        (assoc-in  :k "k"))))

p-himik16:09:43

You're getting a coeffect and returning an effect in your interceptor. Since it's :after, you should probably stick to just effects and ignore coeffects unless there's no db coeffect.

p-himik16:09:24

So in essence, your interceptor is completely overriding the db effect.

popeye16:09:42

here context is assoc with :effect :db but the return will contains both coeffect and effect right ? also I refereed code from https://github.com/jgdavey/minesweeper/blob/main/src/main/minesweeper/app.cljs#L185 which I did it in similar way

popeye16:09:01

let me know if my understanding is wrong!

p-himik16:09:32

> but the return will contains both coeffect and effect right ? Yes. But the code that you link to does not take db from coeffects - it does so from effects. And unconditionally, so it assumes that the corresponding event handler always returns the db. Unless something has changed in re-frame that I haven't seen.

naxels20:09:07

Hi all, Iā€™m using [day8.re-frame/http-fx ā€œ0.2.4ā€] for API calls

naxels20:09:31

and when I do only 1 API call with a :on-success and :on-failure, it will work fine

naxels20:09:47

however, in my case, on :on-failure, I want to do another API call

naxels20:09:33

so iā€™ve created the :on-failure reg-event-fx and here as well define a :http-xhrio with a :on-success and :on-failure

naxels20:09:05

however.. this time, I see the API call getting fired (local server), but the :on-success call doesnā€™t seem to get called šŸ˜ž

naxels20:09:27

anyone know why this is / can help me out?

naxels20:09:00

I need to do a double flow in case a token is not found, then re-login the user

p-himik20:09:59

A block of code is worth a thousand words. ;)

naxels20:09:33

(reg-event-fx :failure-http-using-token (fn [{:keys [db]} [ result]] ; retry grabbing token with refreshtoken {:db db :http-xhrio {:method :get :uri (utils/flow-api-url) :params {:r @(subscribe [:refresh-token])} :format (ajax/json-request-format) :response-format (ajax/json-response-format {:keywords? true}) :on-success [:save-token] :on-failure [:failure-http-result]}}))

naxels20:09:51

this is the 2nd call where the failure has occurred on the 1st call

naxels20:09:44

(reg-event-fx :save-token tokens-interceptor (fn [{:keys [db]} [_ return-json]] (js/alert return-json) (let [data (:data return-json)] {:db (assoc db :tokens {:token (:accessToken data) :refreshtoken @(subscribe [:refreshtoken])}) :dispatch [:set-active-nav :settings]} )))

naxels20:09:51

here is the :save-token

naxels20:09:07

the (js/alert return-json) fires, the :dispatch doesnā€™t

naxels20:09:16

and the tokens-interceptor doesnā€™t either

naxels20:09:52

very strange behavior, because previously i did an assoc-in db :tokens to only update :token, but then my :refresh-token was wiped out

naxels20:09:08

{:db (assoc-in db [:tokens :token] (:accessToken data))}

naxels20:09:41

(interceptor that saves the tokens to localstorage, somehow wiped it in localstorage, only saving :tokens :token)

p-himik20:09:29

First of all, just in case, I'm gonna mention that using @(subscribe ...) in an event handler is an anti-pattern. If you open the JS console, there will be warnings from re-frame about it. Another thing worth pointing out is that js/alert is blocking. I don't really know how you test it, but until you close that pop-up, none of the following code will be executed. Apart from that, I don't notice anything obviously wrong. But I would definitely suggest using js/console.log instead of js/alert to debug things.

naxels20:09:06

good point

naxels20:09:21

iā€™m using the alert to ensure i get popupā€™s in expected order

naxels20:09:56

(reg-event-fx :save-token tokens-interceptor (fn [{:keys [db]} [_ return-json]] (js/alert return-json) (js/alert (:tokens db)) (js/alert db) (let [data (:data return-json)] {:db (assoc-in db [:tokens :token] (:accessToken data)) :dispatch [:set-active-nav :settings]})))

naxels20:09:59

is what I have now

p-himik20:09:37

I would still use js/console.log - it does preserve order. It even supports groups with js/console.group and js/console.groupEnd.

naxels20:09:10

the return-json: provides the result the (:tokens db) is NULL šŸ˜ž the db seems to only contain the map of :token en :refresh-token

naxels20:09:22

hmm, i believe that is where the problem is, itā€™s not the full db

p-himik20:09:37

Check your interceptor.

naxels20:09:08

(def tokens-interceptor [(path :tokens) ->local-store])

naxels20:09:13

(def ->local-store (after tokens->localstore))

naxels20:09:30

(defn tokens->localstore [tokens] (tap> tokens) (let [actual-tokens (:tokens tokens)] (.setItem js/localStorage ā€œtokensā€ (str actual-tokens))))

naxels20:09:39

(a (tap> in there for debugging reasons)

p-himik20:09:52

Well, there you have it - the db there is actually (:tokens app-db) because of that path interceptor.

naxels20:09:23

but that should only fire AFTER all events took place?

naxels20:09:21

i mean in my other reg-event-fx called :save-tokens, it works as expected

p-himik20:09:10

A path interceptor replaces the :db coeffect in its "before" stage and puts the resulting effect in the right place it its "after" stage.

naxels20:09:45

hmm, for some reason (js/console.log) doesnā€™t seem to be working for me in Safari - no output

naxels20:09:26

iā€™m confused then why this works as expected: (reg-event-fx :save-tokens tokens-interceptor (fn [{:keys [db]} [_ return-json]] ; (js/alert (str ā€œSUCCESS: ā€ return-json)) (let [data (:data return-json)] {:db (assoc db :tokens {:token (:accessToken data) :refreshtoken (:refreshToken data)})})))

naxels20:09:50

also has same interceptor, also does a keys on db and assocā€™s to the db

p-himik20:09:01

> hmm, for some reason (js/console.log) doesnā€™t seem to be working for me in Safari - no output Maybe js/console.log is overwritten by something - you can check by executing console.log(1) on a different web page. If that doesn't work, maybe your JS console filtering is set to something. I don't use Safari myself so can't tell. > iā€™m confused then why this works as expected: My bets are on it not actually working like it should. In the end, it will result in the db having 2 nested :tokens.

naxels20:09:39

could i solve this by removing the (path ) you think?

p-himik20:09:16

Of course.

naxels20:09:56

so i removed it

naxels20:09:12

and i canā€™t tell for sure yet if itā€™s working

naxels20:09:36

but the tokens->localstore fn now has the entire :db thatā€™s for sure

naxels20:09:31

iā€™m trying (js/console.log "a") in the REPL, but no message anywhere either hmm

naxels20:09:55

while (js/alert "a") gives instant reaction in the REPL browser window

naxels20:09:12

a, finally got it working in the REPL browser window

naxels20:09:27

in that window, there was a filter

naxels20:09:17

localstorage token and refreshtoken now seem to work šŸ™‚

naxels20:09:25

thanks, removing (path solved it!

šŸ‘ 1
naxels20:09:39

i really thought, looking at the re-frame todomvc that it would do everything after the event ha, not before

naxels21:09:26

for some reason, refreshing the entire browser window

naxels21:09:34

now it seems that js/console.log works

naxels21:09:36

very strange

naxels21:09:52

however, THANK YOU very much! has been bugging me for hours finding out what went wrong

p-himik21:09:42

No problem, glad it worked. :)