Fork me on GitHub
#re-frame
<
2021-08-03
>
achikin12:08:54

I’m trying the new :fx feature and the doc states that within :fx the ordering is sequential. I’m have two effects in my :fx handler

:fx [[:dispatch [:a 1]
     [:dispatch [:b 2]]
The issue is that :a is and fx effect and it emerges it’s own sub effects. As I can see from the logs - those sub-effects are executed after :b

achikin12:08:31

Is that expected? How can I guarantee that sub-effects of :a are executed before :b?

achikin12:08:27

I have changed :a so that it dispatches it’s subeffects via :fx but still no luck

emccue13:08:17

@achim the reason is that the fx is a queue

emccue13:08:27

lets say :a dispatches :c and :d

emccue13:08:31

queue looks like this

emccue13:08:41

popped: 
queue: [:a :b]

emccue13:08:50

popped: :a
queue: [:b]

emccue13:08:03

popped:
queue: [:b :c :d]

emccue13:08:28

and the answer is to not dispatch other events within your event

emccue13:08:44

just make helper functions that will do the state updates and include the fx

emccue13:08:21

(defn what-a-did [db]
  {:db (... db ...)
   :fx [[http ...] [other-actual-effect ...]]})

(defn what-b-did [db]
  {:db ....
   :fx ....})

(rf/reg-event-fx
  ::event-name
  (fn [{:keys [db]} _]
    (let [composed (exercise-for-the-reader what-a-did what-b-did)]
      (composed db))))

currentoor21:08:54

I’ve got an HTML color picker and it fires events very rapidly when the user is changing the color. What’s the best place to debounce this change? Normally, I’d debounce in the UI on-change handler with goog.functions/debounce so I don’t have the overhead of having a million events being processed. Is that frowned upon? It feels less pure based on the docs I’ve read about re-frame, but it seems more pragmatic than debouncing within the even handlers.

currentoor22:08:28

(defn color-input [label {:keys [key value]}]
  (let [on-change (fn [^js evt]
                    (let [v (-> evt .-target .-value)]
                      (re-frame/dispatch [::events/update-user-preference key v])))
        state     (reagent/atom {:on-change (gfun/throttle on-change 200)})]
    (fn [label {:keys [key value]}]
      [:div.form-group
       [:label {} label]
       [:input {:type      "color"
                :value     value
                :on-change (:on-change @state)}]])))
That’s what I’m thinking, it seems to work as expected and I think I need to put the throttled function into local state to avoid a memory leak. It’s been a while since I’ve used React.

alexdavis22:08:21

Dispatch-debounce and dispatch-throttle are built into reframe, you could either use those or look at the implementations for reference

p-himik06:08:55

They are not built into re-frame. :dispatch-debounce is offered by e.g. this lib: https://github.com/7theta/re-frame-fx No idea what offers :dispatch-throttle - I've never seen it.

👍 2
alexdavis09:08:07

My mistake, I remember Daniel talking about it and have used it on projects but seems like they decided not to put them in the core library https://github.com/day8/re-frame/pull/258, anyway that link has the implementations and discussions

currentoor23:08:41

@U2FRKM4TW throttle is much like debounce, expect it fires the first an last event whereas debounce only fires the last event

currentoor23:08:34

at least that’s the goog.functions/throttle

p-himik08:08:36

By "what offers" I meant a library that registers that effect.