Fork me on GitHub
#cljfx
<
2020-10-12
>
Remy16:10:00

Hi @vlaaad, I'm trying to update a label while and after another button-triggered operation takes place. Eg. displaying "Loading" and "Done". I got inspired by (copied) parts of   https://github.com/cljfx/cljfx/blob/master/examples/e18_pure_event_handling.clj .

;; Option 1. Dispatching two events (as per the conversation a few weeks ago)
(defmethod handler-fn ::entrypoint1 [{:keys [fx/context]}]
  (let [config (fx/sub-val context :config)]
    [[:dispatch {:event-type ::loading-status}]
     [:dispatch {:event-type ::processing
                 :config config}]]))

;; Option 2. Single dispatch, passing also a :context key to wrap-effects
(defmethod handler-fn ::entrypoint2 [{:keys [fx/context]}]
  (let [config (fx/sub-val context :config)]
    {:dispatch {:event-type ::processing
                 :config config}
     :context (fx/swap-context context assoc :status "Loading...")}))

(defmethod handler-fn ::loading-status [{:keys [fx/context]}]
  {:context (fx/swap-context context assoc :status "Loading...")})

(defmethod handler-fn ::success-status [{:keys [fx/context]}]
  {:context (fx/swap-context context assoc :status "Done!")})

(defmethod handler-fn ::processing [{:keys [fx/context config]}]
  (Thread/sleep 2000)
  {:dispatch {:event-type ::success-status}})

;;;;;;;;;;;;

(defn root [{:keys [fx/context]}]
  {:fx/type :v-box
   :children [{:fx/type :button
               :text "Option1"
               :on-action {:event-type ::entrypoint1}}
              {:fx/type :button
               :text "Option2"
               :on-action {:event-type ::entrypoint2}}
              {:fx/type :label
               :text (or (fx/sub-val context :status) "")}]})
cljfx 1.7.10 and `java 11` After reading some of `wrap-effects`  source, I realized dispatching  keys or tuples are processed synchronously. So whichever key or tuple is last will define the version of the context the UI is going to look at. Also, it will inevitably block the UI until all dispatches finish their job. I guess I can work around this by calling `Thread/sleep` in another thread and call the handler directly as a callback. I wanted to ask if there was some recommended way to do this or an example I missed. Thank you in advance and sorry if this belongs to the beginners' channel :)

vlaaad17:10:41

Hi @remy, great question 🙂 The answer is don't block UI thread — you should perform your blocking computations in another thread and then dispatch new events from there, effects receive dispatch function as a second argument, you can use that. Example in the same e18: https://github.com/cljfx/cljfx/blob/master/examples/e18_pure_event_handling.clj#L28-L48

vlaaad17:10:23

http-effect is an effect function, it receives dispatch! which is event dispatcher, and does asynchronous http requests, and then dispatches new events on response/error

Remy19:10:52

That makes a lot of sense. Thanks again!