Fork me on GitHub
#re-frame
<
2021-04-19
>
Dmytro Bunin09:04:38

Is there a way to detect an error in an effect? I would like to add a custom error handler for the effect that I don’t control and was wondering if this was possible?

p-himik09:04:37

There's not built-in functionality, but you could wrap that third-party effect handler with your own error handling by first retrieving it with (re-frame.registrar/get-handler :fx that-effect-id) and then just calling it as a function within your own effect handler Do note that re-frame.registrar/get-handler is not a public API.

Dmytro Bunin10:04:59

thanks, nice option

andre09:04:02

Hey lovely re-framers 🙂 re-frisk 1.5.0 is here

🎉 23
superstructor00:04:32

Thanks @U0CC9TJ11 I have updated re-frame-template to use the latest re-frisk release.

❤️ 4
andre09:04:21

[re-frisk "1.5.0"]

andre09:04:38

• render and force update traces • watching keys in app-db • view by subs filtering

andre09:04:29

it doesn't show views names in the demo because of optimization, but they will be shown in dev

Ronny Li23:04:43

Hi everyone, what's the best practice for checking for mistakes in events and subscriptions? For example, I recently deleted a subscription that was still being used (by accident of course). It would be great to set up something that automatically alerts me to these inconsistencies in the future!

p-himik23:04:04

If you mean something like static analysis to detect such things, then maybe #clj-kondo could be used, or at least something that it uses itself.

p-himik23:04:24

But it won't be robust because you can create and use subscriptions and events dynamically.

emccue23:04:34

@U01BRM3MQET I am in no way who you should go to for best practices, but anything you can tie to a var you can get compiler error if you mess up

Ronny Li23:04:10

thanks everyone! Great suggestions!

emccue23:04:11

(def get-stuff [db id]
   ...)

(rf/reg-sub 
  ::stuff
  (fn [db id]
    (get-stuff db id)))

(defn subscription:get-stuff
  [id]
  (rf/subscribe [::stuff id]))

emccue23:04:10

keeping in mind I define my events like this

Lu23:04:17

Actually, tracking missing events/subs should be pretty straight forward, as you get subscription nil and event not found errors logged in the console.. I’ve never had to spend more than a few seconds to realize what was missing

emccue23:04:59

(def event:event-name ::event-name)

(defn event-name [args]
  [event:event-name args])

(defn handler:event-name
  [{:keys [db]} args]
  {:db ...
   :fx ...})

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

👍 6
emccue23:04:06

so i'm maybe a little crazy

p-himik23:04:23

Yeah, but that works only if something does happen that uses that sub or event. If you never click a particular button and don't have a test for it, it might end up being sent to the production. (answering to Lu)

Lu23:04:11

Yeah true.. I mean definitely something to avoid but it won’t harm the app 😅

Ronny Li23:04:20

@U3JH98J4R very interesting... A little crazy but maybe that's the genius behind it :P

emccue23:04:52

I do have a justification, but the world isn't ready

👀 2
p-himik23:04:58

Let me guess - so you always require the necessary namespace with the right calls to reg-event-*? :)

Ronny Li23:04:14

I'm very curious now!

p-himik23:04:45

I do something similar but more lazy and less robust:

(ns some.stuff
  (:require [re-frame.core :as rf]))

(rf/reg-sub ::value
  (fn [db _]
    (:value db)))

(rf/reg-event-db ::set-value
  (fn [db [_ new-value]]
    (assoc db :value new-value)))

(ns other.things
  (:require [re-frame.core :as rf] [some.stuff :as stuff]))

(defn input []
  [:input {:value @(rf/subscribe [::stuff/value]), :on-change #(rf/dispatch [::stuff/set-value %])}])

👍 2
emccue23:04:32

Thats part of it, but more importantly we only ever use :db and :fx so we can compose event handlers and write tests like

emccue23:04:09

(let [process (custom-compose 
                #(handler:focus-on-field % (focus-on-field))
                #(handler:typed-in-field % (typed-in-field "a"))
                #(handler:typed-in-field % (typed-in-field "b")))]
 (is (= (:db (process (...initial db state)))
        ...asserted db state...))
 (is (contains-some-effect-we-want-to-assert 
       (:fx (process (...initial db state))))))
     

🤯 4
emccue23:04:27

and moving towards banning use of :dispatch within event handlers so we can always make these assertions and state changes happen "atomically"

👍 4
lilactown00:04:44

reg-* should really be macros that def vars don't @ me 😉

👍 7
2
prnc12:04:49

is this > (def event:event-name ::event-name) some kind of namespacing by convention, i.e. the use of : in the symbol there? @U3JH98J4R

emccue14:04:58

might macro it up at some point if the pattern holds, but for now biting the bullet of typing so we don't get hard locked in

emccue14:04:01

so for @U2FRKM4TW's example we would do this

;; Events
(def event:user-typed ::user-typed)

(defn user-typed [text]
  [event:user-typed text])

(defn handler:user-typed
  [{:keys [db]} [_ text]]
  {:db (update db ::model/page-state
                  :user-input assoc text)
   :fx []})

(rf/reg-event-fx event:user-typed handler:user-typed)
;; view
(defn input [{:keys [user-input]}]
  [:input {:value user-input
           :on-change #(rf/dispatch (events/user-typed %))}])

👍 3
p-himik15:04:17

Where would you use user-typed without dispatch?

emccue16:04:11

in the tests like bove

p-himik16:04:27

Ah, I see now, thanks.