Fork me on GitHub
#reagent
<
2020-12-31
>
e12:12:47

So I have the following set of actions I want to have happen in my app: • Turn some circles yellow one second after the other • Then turn the circles red for a half second or so before turning grey • In between the circles being red and grey, issue an event (It’s meant to simulate a countdown and then a camera flash). I have the following code:

(defn timeout [event time]
  (js/setTimeout
   (fn []
     (rf/dispatch event))
   time))

(rf/reg-fx
 :timeout-fx
 (fn [args]
   (if (= (type args) map)
     (timeout (:event args) (:time args))
     (doseq [event args]
       (timeout (:event event) (:time event))))))

(rf/reg-event-db
 ::set-timer
 (fn [db [_ val]]
   (camera-q/set-timer db val)))

(rf/reg-event-fx
 ::countdown
 (fn []
   (doseq [i [1 2 3]]
     (timeout [::set-timer i] (* 1000 i)))))

(rf/reg-event-fx
 ::begin-countdown
 (fn []
   {:fx [[:dispatch [::countdown]]]
    :timeout-fx [{:event [::set-timer 4]
                  :time 3500}
                 {:event [::update-active-photo]
                  :time 3500}
                 {:event [::set-timer 0]
                  :time 4300}
                 ]}))

# components subscribe to timer value that determines color, blah blah
It …. works, but it feels wrong? I’m thinking there must be a better, more idiomatic way of chaining these events? (I’m also unhappy with my poor man’s implementation of multiarity with timeout-fx, but wasn’t sure how else to do it.)

p-himik12:12:21

A few things: - camera-q/set-timer should not have any side effects - The ::countdown event handler should use the :timeout-fx effect instead of calling timeout directly - The ::begin-countdown event handler should ideally either use :fx for both :dispatch and :timeout-fx or just have both :dispatch and :timeout-fx at the top level, without :fx Apart from that, I don't see any issues.

e12:12:10

Thanks! Last two points make sense to me. camera-q/set-timer is modifying the db (it’s just (assoc-in db [blah blah blah] val)…. so if I’m not modifying the db there, where would I issue that necessary change?

p-himik12:12:25

You're not modifying the db there, you're creating a brand new value since the data structure is immutable. And it's completely fine, it's how it's supposed to be. :)

e12:12:14

True, that. Gotta beat the Python out of my brain 😉 Appreciate the help!

p-himik12:12:14

Ah, a fellow "Python expat". :D Any time.

afleck14:12:57

what’s the minimum version of React compatible with reagent 1.0.0? can I use react 16.14.0 or do I need 17.x?

👍 3
3
skykanin14:12:39

Is it possible to tell reagent to render some component as a PureComponent ? Or can it check that automatically?

emccue20:12:11

(defn timeout [event time]
  (js/setTimeout
   (fn []
     (rf/dispatch event))
   time))

(rf/reg-fx
 :timeout-fx
 (fn [args]
   (timeout (:event args) (:time args))))

(rf/reg-event-db
 ::set-timer
 (fn [db [_ val]]
   (camera-q/set-timer db val)))

(rf/reg-event-fx
 ::countdown
 (fn []
   (doseq [i [1 2 3]]
     (timeout [::set-timer i] (* 1000 i)))))

(rf/reg-event-fx
 ::begin-countdown
 (fn []
   {:fx [[:dispatch [::countdown]]
         [:timeout-fx {:event [::set-timer 4]
                       :time 3500}
         [:timeout-fx {:event [::update-active-photo]
                       :time 3500}]
         [:timeout-fx {:event [::set-timer 0]
                       :time 4300}]]}))

emccue20:12:28

you can just use the fx key instead of that multiple arity stuff

emccue20:12:01

and really, for stuff like the timer value

emccue20:12:41

that can be computed based on the current time, so ymmv with regards to just setting the current time in the model and computing

emccue20:12:14

and i missed that being explained in the replies

😄 3