Skip to content

Instantly share code, notes, and snippets.

@mike-thompson-day8
Last active August 10, 2020 12:32
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mike-thompson-day8/1388e68391f4c6c1373c9555c08c7114 to your computer and use it in GitHub Desktop.
Save mike-thompson-day8/1388e68391f4c6c1373c9555c08c7114 to your computer and use it in GitHub Desktop.

Warning: this is just me musing and soliciting stimulating opinions. None of this may happen.

On Writing re-frame Event Handlers

Aside #1:

There should be one β€” and preferably only one β€” obvious way to do it
-- Tim Peters

re-frame2 won't have two ways to register an event handler. There will only be reg-event-fx (and no re-frame-db). The -db variation was meant to simplify, but having two ways to do something does not simplify.

Actually, there won't even be reg-event-fx ... but there will be an equivalent ... do not be alarmed.

Using Data Litterals

reg-event-fx currently allows you to register an event handler, and the handler returns a map, like this:

{:db        data1 
 :dispatch  data2
 :gQL       data3
}

To me, it improves readability if you return a map literal and write your event handler like this:

(rf/reg-event-fx 
  :some-id 
  (fn [cofx event]
    (let [ ... ]   ;; in here calculate data1, data2, and data3
      ;; explicitly returning a map literal improves readability IMO 
      {:db        data1 
       :dispatch  data2
       :gQL       data3}  
      )))    ;; yeah, I know this is bad. Only done to isolate the map. 

But it can get more messy if you conditionally need to return an effect:

(fn [cofx event]
  (let [ ... ]   ;; in here calculate data1, data2, and data3
    ;; return the :gQL key conditionally
    (merge 
      {:db        data1 
       :dispatch  data2}  
      (when cond1 {:gQL data3})   ;; conditionally add an effect
    ))   

Now I'm using merge. Can it be simpler?

So, Maybe This

re-frame2 event handlers might allow you to, optionally, return a vector of effects (and not a map).

Like this:

(fn [cofx event]
  (let [ ... ]
    [   ;; returning a vector of maps, instead of a map
      {:db        data1}
      {:dispatch  data2}
      (when cond1 {:gQL data3})   ;; conditionally add an effect, nils ignored later
    ]
    )))    

Notes:

  • I'm programming with data and not merge.
  • I'm maximising my use of data literals. To me, the resulting code is easier to understand.
  • :dispatch-n is no longer necessary, just add n :dispatch effects. Of course, this generalises to every effect. Think about multiple :http or :db-crud effects.
  • it makes conditional effects easier
  • allows effects to be ordered. The existing method, using a map, does not allow ordering (only necessary in some very special cases)

In summary, the DSL is slightly more expressive, at the cost of nesting. (Just to be clear: returned values - effects - are written in a DSL which you help to create via your use of reg-fx. Puzzled by this idea? See more here)

Your thoughts?

@ioRekz
Copy link

ioRekz commented Jul 12, 2019

I agree with everything in there.

I also like that we can more easily compose vector of effects.
In some cases, it can be preferable to reuse and compose them so everything happens in 1 frame. (as opposed to re-dispatch a new event).

Would we need / could we provide a reduce function to be smarter when dealing with effects such as a graphql query?
I personally never used graphql but I have some custom effects that could benefit from reduction.

I'm also wondering if one of the effect maps in the vector can have more than 1 entry? What can it be used for?

@gadfly361
Copy link

gadfly361 commented Jul 12, 2019

I think both of those changes would be great πŸ‘Œ

@fmnoise
Copy link

fmnoise commented Jul 13, 2019

I like the idea and looking forward for it

@0xbase12
Copy link

Definitely, would be great to be able to compose vector of effects.

@realgenekim
Copy link

I love it! Easy to understand, and I love the ability to dispatch multiple events. Thanks for your amazing work! πŸŒˆπŸŒˆπŸ‘πŸ‘

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment