This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-10-12
Channels
- # aleph (8)
- # announcements (9)
- # babashka (15)
- # beginners (91)
- # calva (54)
- # chlorine-clover (3)
- # cider (25)
- # clj-kondo (9)
- # cljfx (4)
- # cljsrn (12)
- # clojure (40)
- # clojure-australia (2)
- # clojure-europe (77)
- # clojure-nl (10)
- # clojure-spec (22)
- # clojure-uk (9)
- # clojurescript (39)
- # conjure (12)
- # cursive (8)
- # datascript (17)
- # datomic (22)
- # emacs (2)
- # expound (6)
- # fulcro (25)
- # kaocha (7)
- # malli (9)
- # meander (5)
- # off-topic (13)
- # pathom (8)
- # pedestal (5)
- # portal (1)
- # rdf (58)
- # re-frame (65)
- # reagent (15)
- # sci (3)
- # shadow-cljs (50)
- # test-check (6)
- # testing (3)
- # tools-deps (1)
- # vim (7)
- # xtdb (10)
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 :)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