Fork me on GitHub
#re-frame
<
2021-03-31
>
Kira Howe14:03:45

Morning (or afternoon, or evening) Clojurians.. I’m wondering if someone more advanced can offer a quick suggestion about the best way to dispatch multiple events with reframe. I have event handlers already for two things I want to do on a certain click (reset some ui state and navigate to a new route). What’s the re-frameiest way to write that? My attempts so far include 1. just calling some function that dispatches both events one after the other and 2. a new event handler that looks kind of like:

(rf/reg-event-fx
 :composite/event
 [validation-interceptor]
 (fn [_ _]
   {:fx [[:dispatch [:event/one]]
         [:dispatch [:event/two]]]}))

Kira Howe14:03:06

is there better way, or a right way to do this, or is it a case of “whatever works”?

jkxyz14:03:22

Using the :fx effect like that is definitely the right way to go @kiraemclean

Kira Howe14:03:40

cool, thanks!

thheller14:03:40

if its all :dispatch there is also :dispatch-n but I believe :fx is better

Kira Howe14:03:27

it sounds like that’s exactly what I’m looking for! I didn’t notice anything about :dispatch-n

Kira Howe14:03:00

I realize there are probably multiple right ways to do anything, but just curious what’s the “normal” reframe way if there is such a thing.

jkxyz14:03:20

Was going to mention it, but :dispatch-n was deprecated in favor of using :fx with multiple :dispatch effects

Kira Howe14:03:55

ah I see it’s deprecated in my version anyway. thank you for the reference Josh! I missed it.. totally burnt out on reading docs right now.

Kira Howe14:03:03

appreciate the help 🙏 hope you both have a nice day!

jkxyz14:03:22

Likewise ☀️

emccue15:03:57

@kiraemclean Maybe controversial, but I would avoid dispatching at all

emccue15:03:32

just compose functions that return :db and :fx

Kira Howe20:03:00

not sure I understand what you mean. how is this different from the above example that returns :fx?

emccue21:03:47

instead of this

emccue21:03:16

(rf/reg-event-fx 
  :event/one
  (fn [{:keys [db]} _]
    {:db (... db ...)
     :fx (... fx ...)}))

(rf/reg-event-fx 
  :event/two
  (fn [{:keys [db]} _]
    {:db (... db ...)
     :fx (... fx ...)}))

(rf/reg-event-fx
 :composite/event
 [validation-interceptor]
 (fn [_ _]
   {:fx [[:dispatch [:event/one]]
         [:dispatch [:event/two]]]}))

emccue21:03:53

you do this

emccue21:03:21

(defn handler:event-one
  [{:keys [db]} _]
  {:db (... db ...)
   :fx (... fx ...)})
  
(rf/reg-event-fx 
  :event/one
  handler:event-one)

(defn handler:event-two
  [{:keys [db]} _]
  {:db (... db ...)
   :fx (... fx ...)})

(rf/reg-event-fx 
  :event/two
  handler:event-two)

(defn handler:composite-event
  [cofx event]
  ((compose-handlers 
     handler:event-one
     handler:event-two) cofx event))

(rf/reg-event-fx
 :composite/event
 [validation-interceptor]
 handler:composite-event)

emccue21:03:38

where compose-handlers threads through the db and concats anything in :fx

emccue21:03:59

generally you don't need compose to work on Handler, Handler -> Handler , you can have it just work on (db -> {:db, :fx}), (db -> {:db, :fx} -> (db -> {:db, :fx}) if that makes sense

emccue21:03:40

so you might end up with

emccue21:03:26

(defn handler:composite-event
  [{:keys [db]} event]
  ((compose 
     #(handler:event-one {:db %} event)
     #(handler:event-one {:db %} event)) db))

emccue21:03:06

that way you can just call handler:composite-event in a test and you can see exactly the state the db would be in after an event fires

emccue21:03:24

which is a PITA otherwise

emccue15:03:15

managing/testing "what is the state of the app after this event fires" is a hard question otherwise

bastilla18:03:06

Hi there. I do an :http-xhrio to an end point which just delivers text. edn actually!! Now I want my event handler to expect and process edn. Isn't there something like: :response-format (ajax/edn-response-format) I just find (ajax/json-request-format...) and :text. Both fail. Where did I turn for Mars? Pls help me return.

3
jkxyz18:03:35

@bastilla ajax.edn/edn-response-format is what you’re looking for 🙂

🙌 3
3
bastilla19:03:26

Awesome! A million thanks! @josh604

jkxyz19:03:01

No problem. If you’re sending EDN from your backend, you might want to consider using the https://github.com/cognitect/transit-clj format instead. The reason that edn-response-format is not in the ajax.core namespace is because they deprecated it, as EDN isn’t recommended for sending data to the browser

bastilla19:03:30

Ok, good hint. :thumbsup: I'll change it in the long run.

Kira Howe20:03:30

Are there any examples out there of reframe apps that include tests? My struggles are more with getting cljs tests compiling and running than reframe specifically, but reframe is still part of the challenge. I’m wondering if there are any open source examples I can look at.

p-himik20:03:47

Haven't delved too deep, but these real-world projects do have some CLJS tests and use re-frame, if my notes are correct: - https://github.com/district0x/memefactory - https://github.com/district0x/name-bazaar

Kira Howe21:03:24

cool, thank you! looks like they’re using doo for a test runner. interesting to consider.

Kira Howe20:03:51

Also, is anyone successfully using devcards with reframe? I know that’s a bit tricky and I’ve come across several hacks/workarounds to make them play nice with the single global state thing, but no complete implementations. Curious whether anyone has an example of that, too.

Kira Howe20:03:59

So far I’ve just punted it, trying to make view functions pure and use devcards like normal, but it would be cool to be able to use them for more complete views that dispatch events and/or require subscriptions that it wouldn’t make sense to pass in

beders20:03:43

I would be curious about that as well