May 25, 2015

Tetris in clojurescript and re-frame Part 8 - Subscriptions


The last building block in re-frame are the subscriptions. This is to notify the UI if something in the app state changes. These are all we need for now.

The first checks if the application is initialized or not.

(register-sub :initalized? (fn [db _] (reaction (:initalized? @db))))

The second checks if the game was started or not.
(register-sub :started? (fn [db _] (reaction (:started? @db))))

The third checks if the game is paused or not.

(register-sub :paused? (fn [db _] (reaction (:paused? @db))))

And the last one is triggered whenever the score of the game changed.

(register-sub :score (fn [db _] (reaction (:score @db))))

Now we redefine our layout function from part 2:

(defn core []
  (let [tet-width "200px"
        initalized? (rf/subscribe [:initalized?])
        score (rf/subscribe [:score])]
    (if initalized?
        [:canvas#tetris-canv {:height "400px" :width tet-width :style {:background-color "#444444"}}]
        [:div#score {:style {:background-color "#CCCCCC" :width tet-width}} (str "Score: " @score)]]
        (let [started? @(rf/subscribe [:started?])
              paused? @(rf/subscribe [:paused?])]
            {:on-click (cond (not started?) #(rf/dispatch [:start-game])
                             paused? #(rf/dispatch [:unpause-game])
                             (not paused?) #(rf/dispatch [:pause-game]))}
            (cond (not started?) "Start" paused? "Continue" (not paused?) "Pause")]
           [:button.btn.btn-primary {:on-click #(rf/dispatch [:restart-game])} "Restart"]])]]
      [:h4 "Loading..."])))

You can see the added (rf/subscribe [:...]) functions which refer to the (register-sub ...) definitions made before. Now whenever the app state changes the UI will be actualized. This is the part that reagent is responsible for (which wraps react.js).

Tags: tetris clojuresrcipt