re-frame

https://github.com/Day8/re-frame/blob/master/docs/README.md https://github.com/Day8/re-frame/blob/master/docs/External-Resources.md
Kira McLean 2021-03-31T14:18:45.068600Z

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 McLean 2021-03-31T14:19:06.069100Z

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

jkxyz 2021-03-31T14:24:22.070300Z

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

Kira McLean 2021-03-31T14:24:40.070600Z

cool, thanks!

thheller 2021-03-31T14:26:40.071400Z

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

Kira McLean 2021-03-31T14:27:27.071900Z

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

Kira McLean 2021-03-31T14:28:00.073300Z

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.

jkxyz 2021-03-31T14:28:20.074100Z

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

Kira McLean 2021-03-31T14:28:55.074700Z

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 McLean 2021-03-31T14:30:03.075100Z

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

jkxyz 2021-03-31T14:30:22.075400Z

Likewise ☀️

Kira McLean 2021-03-31T14:30:38.075600Z

thanks 🙂

emccue 2021-03-31T15:14:57.076100Z

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

emccue 2021-03-31T15:15:32.076500Z

just compose functions that return :db and :fx

emccue 2021-03-31T15:17:15.077100Z

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

kennytilton 2021-03-31T16:49:55.077200Z

@p-himik "In this particular case - none." Is that strictly correct? I thought RF, given the explicit :id subscription, would avoid propagating to :root-comp-initial-tab if sth other than :id changed in db.

p-himik 2021-03-31T16:52:30.077400Z

That's true. But in this particular case, the :root-comp-initial-tab subscription is as simple as it can get - it won't matter at all.

p-himik 2021-03-31T16:53:13.077600Z

In fact, if :_id is only used by :root-comp-initial-tab, then that might be a disadvantage even. At the very least, just because of the extra code involved.

kennytilton 2021-03-31T17:02:05.077800Z

I was thinking it important for a noob to RF to grok the short-circuiting of state propagation by RF, regardless of the de facto insignificance in the given use case. No? Still not sure if @ps picked that up, though the doc is indeed extensive.

1👍
bastilla 2021-03-31T18:57:06.090100Z

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.

1✅
jkxyz 2021-03-31T18:59:35.090500Z

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

1🙌1✅
bastilla 2021-03-31T19:03:26.091300Z

Awesome! A million thanks! @josh604

jkxyz 2021-03-31T19:15:01.093800Z

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

bastilla 2021-03-31T19:16:30.094600Z

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

Kira McLean 2021-03-31T20:06:00.094900Z

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

Kira McLean 2021-03-31T20:07:30.096200Z

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.

Kira McLean 2021-03-31T20:08:51.097600Z

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 McLean 2021-03-31T20:09:59.098800Z

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

p-himik 2021-03-31T20:12:47.098900Z

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

beders 2021-03-31T20:37:43.099500Z

I would be curious about that as well

Kira McLean 2021-03-31T21:06:24.099600Z

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

emccue 2021-03-31T21:49:43.099800Z

well, uhh

emccue 2021-03-31T21:49:47.100Z

instead of this

emccue 2021-03-31T21:51:16.100200Z

(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]]]}))

emccue 2021-03-31T21:51:53.100400Z

you do this

emccue 2021-03-31T21:54:21.100600Z

(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)

emccue 2021-03-31T21:54:38.100800Z

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

emccue 2021-03-31T21:55:59.101Z

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

emccue 2021-03-31T21:56:40.101200Z

so you might end up with

emccue 2021-03-31T21:57:26.101400Z

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

emccue 2021-03-31T21:58:06.101600Z

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

emccue 2021-03-31T21:58:24.101800Z

which is a PITA otherwise