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

ClojureScript Web Applications

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest. →
Avatar for Esko Lahti Esko Lahti
September 01, 2017

ClojureScript Web Applications

This talk was given in Small FP Conf 2017 (http://clojutre.org/2017/#reagent).

Reagent is a framework used to create React applications in native ClojureScript. Re-frame offers a state container framework that is often used with Reagent.

In this talk we'll go through some basics of developing functional web applications with ClojureScript. This talk will also cover some common Reagent/re-frame design problems using a real-world example.

Avatar for Esko Lahti

Esko Lahti

September 01, 2017

Other Decks in Technology

Transcript

  1. (ns dob (:require #?(:clj [clj-time.core :as t] :cljs [cljs-time.core :as

    t]))) (defonce date-pattern #"^(\d{1,2})\.(\d{1,2})\.(\d{4})$") (defn str->dob [dob-str] (try (when-let [[_ day month year] (re-find date-pattern dob-str)] (t/date-time #?@(:clj [(Integer/valueOf year) (Integer/valueOf month) (Integer/valueOf day)] :cljs [(int year) (int month) (int day)]))) (catch #?(:clj Exception :cljs :default) _)))
  2. {:cljsbuild {:builds [{:id "dev" :source-paths ["src/cljs"] :figwheel {:on-jsload "app.core/mount-root"} :compiler

    {:main app.core :output-to "resources/public/js/compiled/app.js" :output-dir "resources/public/js/compiled/out" :asset-path "js/compiled/out" :source-map-timestamp true}}]}}
  3. {:cljsbuild {:builds [{:id "min" :source-paths ["src/cljs"] :compiler {:main app.core :output-to

    "resources/public/js/compiled/app.js" :optimizations :advanced :closure-defines {goog.DEBUG false} :pretty-print false}}]}}
  4. (defn counter-control [value on-click]
 [:input {:type "button" 
 :value value


    :on-click on-click}]) 
 (defn counter-display [count-val] 
 [:span (str "Current count: " count-val)]) 
 (defn counter []
 (let [count-val (reagent.ratom/atom 0)]
 (fn []
 [:div
 [counter-display @count-val]
 [counter-control "+" #(swap! count-val inc)]
 [counter-control "-" #(swap! count-val dec)]]))) props reactive state subcomponents
  5. (re-frame.core/reg-event-db :count-update
 (fn [db [_ on-change]]
 (update db :count on-change)))

    
 (defn counter-control [value on-change]
 [:input {:type "button"
 :value value
 :on-click (fn [event]
 (re-frame.core/dispatch [:count-update on-change]))}]) 
 (defn counter []
 [:div
 [counter-display]
 [counter-control "+" inc]
 [counter-control "-" dec]]) event registration event dispatch state update
  6. (re-frame.core/reg-sub :count
 (fn [db]
 (:count db)))
 (defn counter-display []
 (let

    [count (re-frame.core/subscribe [:count])]
 [:span (str "Current count: " @count)])) 
 (defn counter []
 [:div
 [counter-display]
 [counter-control "+" inc]
 [counter-control "-" dec]]) subscription local reactive state state
  7. (re-frame.core/reg-fx :http
 (fn [{:keys [url dispatch]}]
 (let [{:keys [body]} (http/get

    url)]
 (re-frame.core/dispatch (conj dispatch body))))) 
 (re-frame.core/reg-event-fx :order
 (fn [{:keys [db]} [_ thing]]
 {:db db
 :http {:url (str "/api/order/" thing)
 :dispatch [:handle-order thing]}})) 
 (defn order-button []
 [:input {:type "button"
 :value "Order pizza"
 :on-click (fn [event]
 (re-frame.core/dispatch [:order "pizza"]))}]) effect registration event with effect registration effect dispatch no state update callback
  8. React Component Event Handler Application State C CL C CL

    CLO CLOJ CLOJUR CL CLOJURE Event
 Dispatch State
 Update State
 Subscription
  9. DOM