Skip to content

Latest commit

 

History

History
94 lines (71 loc) · 3.23 KB

2020-07-19.md

File metadata and controls

94 lines (71 loc) · 3.23 KB

Learning Clojure in Public - Week 4 Day 7 (28/35)

Expectations

Low expectations today because, it is a Sunday, and because I no longer have the thread of a specific documentation, or book to follow so I am taking shots in the dark, trying to make things work and learn something at the same time.

The expectation for today is to start building a small re-frame application. Something very simple. It would have made sense for me to build alongside reading the documentation but there's only so many hours in a day, it had to be split and this how I did it. For sure this is improving my understanding of re-frame.

What I learned while building

I started by setting up my views. In my views I needed a wheel, to display a message, and also the result of the spin. For starters, the wheel is simply a button that says "spin".

(defn wheel []
  (let [yn (re-frame/subscribe [::subs/yn])]
    [:div
    [:h3 "The wheel says " @yn]
    [:input {:type "button" :value "Spin"
             :on-click #(re-frame.core/dispatch [:spin])}]]))

The view is subscribing to the value of yn in the database. I also added a random message, with wheel themed pun (I got a lot more puns coming!).

(def sayings ["Der wheel zur macht"
              "Wheel power"
              "Boys wheel be boys"
              "Free wheel offering"
              "Time wheel tell"
              "Wheel Wheaton"])

(defn the-wheel-says []
  (sayings (int (rand (count sayings)))))

Finally we can tie this up together in the main element:

(defn main-panel []
    [:div
        [:h1 "Hail the Wheel!"]
        [:h2 [the-wheel-says]]
        [wheel]])

After that I need to create the event, that happens on click:

(def yes-no-string ["YES" "NO"])

(re-frame/reg-event-db
 :spin
 (fn [db]
   (let [spin-result (yes-no-string (int (rand 2)))]
   (js/console.log "Spin result:" spin-result)
   (assoc db :yn spin-result))))

However, the event handler should remain a pure function so for this I should be using a coeffect.

(re-frame/reg-cofx
  :yn
  (fn [cofx _]
    (assoc-in cofx [:db :yn] (yes-no-strings (int (rand 2))))))

However, since I am not just merely updating the db I need to switch the reg-event-db to a reg-event-fx. This StackOverflow answer has more details:

If your handler needs to access co-effects/produce effects then you'd use reg-event-fx and get the :coeffects value (and :db if necessary) from the handler's input. A common use case is when you need to access browser storage (e.g. cookies, local storage) but want to keep your handlers free of side-effects. So we end up with:

(re-frame/reg-event-fx
 :spin
 [(re-frame/inject-cofx :yn)]
 (fn [cofx _]
   {:db (assoc (:db cofx) :yn (:yn cofx))}))

(re-frame/reg-cofx
  :yn
  (fn [cofx _]
    (assoc cofx :yn (yes-no-strings (int (rand 2))))))

Takeaways

Putting together this very simple re-frame loop was easy to get started with but understanding how to use the coeffects was a lot more complicated, which is ironic because it was not really needed in case, yet I wanted to be as as close to real world conditions as possible.

Tomorrow I will focus on styling the wheel, maybe make it spin as well!