This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-08-04
Channels
- # announcements (6)
- # beginners (207)
- # calva (39)
- # cestmeetup (35)
- # chlorine-clover (36)
- # clj-kondo (15)
- # clj-together (1)
- # cljsrn (2)
- # clojure (110)
- # clojure-europe (8)
- # clojure-italy (9)
- # clojure-nl (2)
- # clojure-uk (5)
- # clojurescript (61)
- # conjure (4)
- # cursive (1)
- # datalog (3)
- # datomic (22)
- # emacs (8)
- # events (2)
- # figwheel-main (11)
- # fulcro (23)
- # graalvm (16)
- # graphql (1)
- # helix (4)
- # jobs (5)
- # jobs-discuss (4)
- # malli (3)
- # mid-cities-meetup (13)
- # off-topic (58)
- # pathom (12)
- # re-frame (30)
- # reagent (45)
- # reitit (1)
- # reveal (7)
- # sci (2)
- # shadow-cljs (173)
- # spacemacs (1)
- # sql (1)
- # test-check (5)
- # xtdb (13)
@joservarelaf Holy cow! I’m glad I grabbed a screenshot of your comments an hour ago in that thread, because it’s gone now, due to Slack free tier limits! 🙂 WHEW!
Lol no way wait
Had it saved, pressed back and took screenshots haha I think we’re on to something here I’m down to hack on this during the weekend
Thank you!! And you can find the thread here, too, on the Clojurians Slack archive: https://clojurians-log.clojureverse.org/re-frame/2020-07-26
oh wow I wasnt aware this existed
@U07FP7QJ0 is responsible for the miracle that is the Clojurians Slack Archive! Thanks @U07FP7QJ0! 🙂
As a tip, you can find threads you've participated in near the top of the left sidebar in Slack. They seem to stay there for quite a while!
Hi, @mikethompson — I had a great time prototyping a program that assembled an event dispatch graph from an events.cljs file, to help me make sense of a sprawling call graph that built up over 4.5 years!
I wrote up an experience report here: https://docs.google.com/presentation/d/1yf6f7OYFWYADZ59nrSSNWjiw8zf-yt60yBjWqrJFPdA/edit#slide=id.p
Mike, there’s a question directed to you at the end — can you point me to where in re-frame-10x
I might find the event log, from which I could render a similar graph, or any advice?
For y’all’s amusement, here’s my dispatch graph, with 107 nodes, 69+ edges (incomplete) — guess which part involves UI with multiple modes? 🙂 (Answer is in the Google Slides deck linked above.)
@genekim Thanks, I just had a quick skim ... I'll have a proper read later As I skimmed, I got a little struck by slide 12 ... Slide 21 could be done with this
(reg-event-fx
::edit-car-key-down
[check-spec-interceptor]
(fn [_ [_ {:keys [keycode]}]]
(if (= 27 keycode)
{:dispatch [::cancel-card-name]}
{}))
Notes:
1. You don't have to return a :db
effect in a reg-event-fx
2. Instead of having the view dispatch ::edit-car-key-down
it almost seems as it should be the one emitting a
::cancel-card-name`. Events should model user intent. The nil return path is a dead giveaway
Also on slide 11 can be done like this:
:dispatch-n [[::first-one :blah :foo]
(when (not= blah) [:next-card])]
Notes:
1. when
is friend when you want nil
on else
2. :dispatch-n
will ignore nil
Overall Notes: 1. it looks as though you have one event emitting other events as a way of not simply calling a function (but I'm not 100% on that ... will have to read more) 2. it looks as if you might need a broader state-machine to manage the "higher level' dynamics (you say that you can't keep "the overall flow" in your head)
🙏🙏🙏 Thanks so much for the critiques!!! And OMG. I feel like a truly terrible person as you typed my (bad) code in from a screenshot. 😱😱😱. Sorry!! PS: for you convenience, here’s the source. (Was listed on slide 2 or so, I think) And i apologize for the embarrassments you’ll find in there. Like a caveman playing a grand piano. 😂😂😂
https://github.com/realgenekim/re-frame-event-graph/blob/master/resources/trello-events.cljs Posted only for your convenience! And thanks again!!!
@mikethompson Your observation about using a state machine(s) is jolting. I can totally see adding one function could take most of the logic out of many of the events. Exciting!
@genekim This is all good. I like seeing how people use re-frame. I'll cycle back later today - morning meetings here
Cool cool. For your amusement, I’ll post a video of the app tomorrow, and maybe I’ll use this as incentive to get all the Trello secrets out of the repo, and publish it. (Something I’ve wanted to do for 4 years. 🙂 (Although it will show everyone to what extent I don’t understand CSS. :rolling_on_the_floor_laughing::rolling_on_the_floor_laughing:
There are only two kinds of people in this world: 1. Those that don't know CSS 2. Those that think they do, except they don't. Not really.
Further Notes:
1. to reduce noise, you should make check-spec-interceptor
a global interceptor (a new feature)
2. It appears as if your calls to interfaces/invoke
and io/display-notification
are side effecting and would ideally be modeled as effects (ie. use reg-fx
)
3. In https://github.com/realgenekim/re-frame-event-graph/blob/master/resources/trello-events.cljs#L355-L363 it appears you are using events instead of function calls. IMO, you should have a function call reset-card
not an event. This function would be given db
arg and return a modified db
. Then you simply call that function in that event handler ... don't dispatch an event to do it. Events are meant to model user intent, not model the low level machinery - good old functions calls do that just fine.
4. I'm sure I don't need to tell you that you should clean up all those side effecting dispatch
calls in reg-event-db
handlers ... but I will any way, just in case :-)
BTW, I know I haven't got the the event knot yet. More later when I get a bit more time.
This is beautiful…
(>defn reset-card
[db] [map? => map?]
(assoc db :current-card-comments []
:current-card-attachments []
:new-comment-text ""))
(>defn set-list
[db list-id] [map? string? => map?]
(assoc db :selected-list list-id))
(comment
(-> {:a 1}
reset-card
(set-list "abc")))
This is even more beautiful — as imperative stuff moves to more declarative…
(re-frame/reg-event-fx
::select-board
[check-spec-interceptor]
(fn [{:keys [db]} [_ board-id]] ; currstate, and new state
(println "::select-board: " board-id)
{:dispatch-n [[::save-and-clear-searchbox]
; if moving card, make sure focus is in search box
(when (= (:left-pane-view db) :leftpane-moving-board)
(io/focus-searchbox ::focus-searchbox))
[::load-board-lists board-id]
[::select-board-next-leftpane-state]]
:db (dbh/select-board db board-id)}))
Wow, this is nice…. made my first reg-fx
.
(re-frame/reg-fx
:load-lists
(fn [board-id]
(check-and-throw string? board-id)
(println ":load-list: fired off go-routine: board " board-id)
(interfaces/invoke interfaces/trello {:command :load-lists
:board-id board-id
:callback ::callback-load-board-lists})))
I have to say your use of guardrails and check-and-throw
impresses me. In my code those things are nonexistent 😹
Haha — your ability to write and run code without Guardrails and check-and-throw
impresses me! Seriously, I pass in wrong stuff all the time, sometimes as an accident or misinterpreting the API.
(Just yesterday in my first reg-fx
posted above, at first I accidentally passed in [board-id]
instead of board-id
and would have spent 10+ minutes trying to figure out why I was getting strange behavior or unreadable, long exception.)
I am able to now, but maybe not when touching it again next year. 😅 I do see real value in type signatures as documentation, and wish it was more common to use them in Clojure!
@mikethompson I’ve been having fun refactoring as you recommended. And I fixed some event names that were clearly misleading… (Scary at first! 🙂 I rearranged some events, and I got to the point where I wanted to reassess how I’ve been doing. I upgraded re-frame so I could make a global interceptor (wow! nice!!) to capture the events, and experimented with rendering the dispatch graph from mermaidJS. (A couple of fun things. It was even more obvious what events were misplaced — it turns out it was the same two boxes that I had highlighted a couple of days ago!) I’ll work on getting this cleaned up, and will post the code I used, just in case it is of any interest to anyone. (Before, I was rendering it in Clojure — this screenshot is being rendered in ClojureScript, using the MermaidJS library.)
@mikethompson I’ve been having fun refactoring as you recommended. And I fixed some event names that were clearly misleading… (Scary at first! 🙂 I rearranged some events, and I got to the point where I wanted to reassess how I’ve been doing. I upgraded re-frame so I could make a global interceptor (wow! nice!!) to capture the events, and experimented with rendering the dispatch graph from mermaidJS. (A couple of fun things. It was even more obvious what events were misplaced — it turns out it was the same two boxes that I had highlighted a couple of days ago!) I’ll work on getting this cleaned up, and will post the code I used, just in case it is of any interest to anyone. (Before, I was rendering it in Clojure — this screenshot is being rendered in ClojureScript, using the MermaidJS library.)