Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ClojureScript and WebSockets and React (Oh, My!)

ClojureScript and WebSockets and React (Oh, My!)

We'll look at a few technologies I used to create a software estimation application:
• Reagent, an interface between ClojureScript and React, a JavaScript library for building user interfaces.
• Sente, a library that uses WebSockets to maintain an interactive communication session between a browser and server.

After this talk, you'll be able to:
• Explain how WebSockets work, and how they're different from a polling approach to client/server communication
• Understand at a high level how React and Reagent work
• Get started with Reagent on your own ClojureScript projects

Michael Stalker

January 26, 2017
Tweet

More Decks by Michael Stalker

Other Decks in Technology

Transcript

  1. PLANNING POKER® ♠️ ♥️ ♣️ ♦️ PLANNING POKER ® is

    a registered trademark of Mountain Goat Software, LLC Sequence of values is (C) Mountain Goat Software, LLC
  2. 3 8

  3. 8 3

  4. (ns planning-poker.message-handler (:require [taoensso.sente :as sente] [planning-poker.notifier :as notifier] [planning-poker.game-table

    :as table])) (defonce players (atom {})) (defmulti message-handler :id) (defmethod message-handler :table/player-joined [{:keys [?data ring-req]}] (table/add-player! players (user-id ring-req) ?data) (notifier/notify-players-updated @connected-uids @players chsk-send!)) (defmethod message-handler :table/player-estimated [{:keys [?data ring-req]}] (table/estimate! players (user-id ring-req) ?data) (notifier/notify-players-estimated @connected-uids @players chsk-send!)) (sente/start-chsk-router! ch-chsk message-handler)
  5. CLOJURESCRIPT • Immutable data structures and locals • Protocols •

    Google’s Closure compiler • Namespaces • Macros
  6. HOW REAGENT WORKS (defn simple-component [] [:div [:p "I am

    a component!"] [:p.someclass "I have ” [:strong "bold"] [:span {:style {:color "red"}} " and red "] "text."]])
  7. HOW REAGENT WORKS (defn simple-component [] [:div [:p "I am

    a component!"] [:p.someclass "I have ” [:strong "bold"] [:span {:style {:color "red"}} " and red "] "text."]]) I am a component! I have bold and red text.
  8. COMPONENTS CAN RENDER COMPONENTS (defn simple-parent [] [:div [:p "I

    use simple-component."] [simple-component]])
  9. COMPONENTS CAN RENDER COMPONENTS (defn simple-parent [] [:div [:p "I

    use simple-component."] [simple-component]]) I use simple-component. I am a component! I have bold and red text.
  10. STATE (def click-count (r/atom 0)) (defn counting-component [] [:div "The

    atom " [:code "click-count"] " has value: ” @click-count ". ” [:input {:type "button" :value "Click me!” :on-click #(swap! click-count inc)}]])
  11. (ns planning-poker.client.game-table (:require [planning-poker.client.cards :as cards] [planning-poker.client.login :as login] [planning-poker.client.players

    :as table-players])) (defn component [players channel] [:div [login/component channel] [:div.game-table [:h1.game-table-heading "Remote Planning Poker"] [cards/component channel] [table-players/component players] [:button.reset "Play a New Round"]]])
  12. (ns planning-poker.client.cards (:require planning-poker.client.extensions)) (def cards ["?" 0 1 2

    3 5 8 13 20]) (defn component [channel] [:ol.cards (doall (for [card cards] ^{:key card} [:li [:button.card card]]))])
  13. (ns planning-poker.client.players (:require [planning-poker.client.player :as player])) (defn component [players] [:div.players

    [:h2 "Players"] [:div.names [:ul (for [[player-id player] @players] ^{:key player-id} [player/component player])]]])
  14. (ns planning-poker.client.login) (defn component [channel] (fn [] [:form.login [:fieldset [:p

    "Remote Planning Poker"] [:input {:name "player-name" :placeholder "Your Name" :auto-focus true}] [:button "Start Playing"]]])))
  15. (ns planning-poker.client.cards (:require [reagent.core :as r])) (def cards ["?" 0

    1 2 3 5 8 13 20]) (defonce active-card (r/atom nil)) ;; Activate card atom and notify server that player estimated (defn select-card [card channel] ...) (defn component [channel] [:ol.cards (doall (for [card cards] ^{:key card} [:li [:button.card {:on-click (select-card card channel) :class (if (active? card) "active" "")} card]]))])
  16. (ns planning-poker.client.players (:require [planning-poker.client.player :as player])) (defn component [players] [:div.players

    [:h2 "Players"] [:div.names [:ul (for [[player-id player] @players] ^{:key player-id} [player/component player])]]])
  17. (ns planning-poker.client.player) (defn component [player] [:li.player [:span.name (:name player)] [:span.estimate

    {:class (cond (:show-estimate? player) :estimate-show (:estimate player) :estimate-hide :else :estimate-waiting)} (when (:show-estimate? player) (:estimate player))]])
  18. (ns planning-poker.client.game-table (:require-macros [cljs.core.async.macros :refer [go]]) (:require [cljs.core.async :refer [>!]]))

    (defn- start-new-round [channel] (fn [event] (go (>! channel [:table/new-round-requested])))) (defn component [players channel] [:div [login/component channel] [:div.game-table [:h1.game-table-heading "Remote Planning Poker"] [cards/component channel] [table-players/component players] [:button.reset {:on-click (start-new-round channel)} "Play a New Round"]]])
  19. IMAGE ATTRIBUTIONS • https://commons.wikimedia.org/wiki/File:Portrait_of_Plato;_bust._Wellcome_M0005618.jpg This file is licensed under the

    Creative Commons Attribution 4.0 International license. https://creativecommons.org/licenses/by/4.0/deed.en This file comes fromWellcome Images, a website operated by WellcomeTrust, a global charitable foundation based in the United Kingdom. Refer to Wellcome blog post (archive). No changes were made, except possibly cropping • https://commons.wikimedia.org/wiki/File:Nineteenth_century_bathtub_grayscale.jpg This file is licensed under the Creative Commons Attribution-Share Alike 3.0 Unported license. https://creativecommons.org/licenses/by-sa/3.0/deed.en Doug Coldwell No changes were made, except possibly cropping
  20. IMAGES WITH NO COPYRIGHT • https://commons.wikimedia.org/wiki/File:Tage_Erlander_1960-tal.jpg • https://commons.wikimedia.org/wiki/File:Dismantling_a_Bathtub_in_the_White_House-02-10-1950.jpg • https://en.wikipedia.org/wiki/Candlestick_telephone#/media/File:Genevieve-Clark-Bain.jpeg

    • https://commons.wikimedia.org/wiki/File:JolsonTelephone.jpg • https://commons.wikimedia.org/wiki/File:Apollo_8_Borman_takes_phone_call_from_LBJ.jpg • https://commons.wikimedia.org/wiki/File:Don_Knotts_Jim_Nabors_Andy_Griffith_Show_1964.JPG • https://commons.wikimedia.org/wiki/File:Joseph_Kearns_Jay_North_Billy_Booth_Herbert_Anderson_D ennis_the_Menace_1962.JPG