Respo
Guide
API Docs
Community
GitHub
Respo: a virtual DOM library in ClojureScript.
Component Nesting

(defcomp comp-child [prop-b]
  (div {} (<> (str prop-b))))

(defcomp comp-demo [prop-a prop-b]
  (div {:class-name "demo" :style {} :on {}}
    (<> (str prop-a))
    (comp-child prop-b)))

; respo.macros/div
; respo.macros/<>
; respo.macros/defcomp
Inline Styles

(def style-page
  {:background-color (hsl 240 80 80)
   :font-size "14px"})

(div {:style (merge ui/fullscreen ui/column style-page)})

; hsl.core :as hsl
; respo-ui.style :as ui
Event Handling

(defn on-click [e dispatch! mutate!]
  (dispatch! :confirm "from button")
  (println "clicked"))

(div {:style ui/button
      :on-click on-click}})

; respo-ui.style :as ui
Hot Swapping

; triggered by build tool
(defn reload! []
  ; remove caches of component tree
  (clear-cache!)
  ; now rendering process use no caches
  (render-app!)
  (println "Code update."))

; respo.core/clear-cache!
Store

; atom to define mutable store
(defonce *store
  (atom
    {:tasks []
     ; this is states
     :states {}}))

(defn updater [store op op-data]
  (case op
    :states (update store :states (mutate op-data))
    :add-task (add-task store op-data)
    store))

(defn dispatch! [op op-data]
  ; mutate store
  (reset! *store (updater @*store op op-data)))

; watch store changes
(add-watch *store
  (fn [] (println "store is changed!")))
State Management

(defn on-input [e dispatch! mutate!]
  ; send next state to store, internally using dispatch!
  (mutate! (:value e)))

(defcomp comp-field [states]
  (let
    ; states are inside store as a states tree
    ; use `or` to specify initial state
    [state (or (:data states) "")]
    (div {}
      (div {}
        (<> span "name" nil))
      (input {:placeholder "name"
              :value state
              :on-input on-input}))))

(defcomp comp-parent [states]
  (div {}
    ; create a sub-cursor in states tree, pass down to it
    (cursor-> :field comp-field states)))

; respo.macros/cursor->