Skip to content

Instantly share code, notes, and snippets.

@Otann
Created April 12, 2017 22:49
Show Gist options
  • Save Otann/dbc659acd4520ee0279e9605d62d4ade to your computer and use it in GitHub Desktop.
Save Otann/dbc659acd4520ee0279e9605d62d4ade to your computer and use it in GitHub Desktop.
Redux in Clojure
(ns sample.components
(:require [rum.core :as r]
[clojure.string :as str]
[sample.redux :refer [dispatch action]]))
(r/defc ui-form
[state]
[:.app
[:h1 (str "Hello, " (:name state))]
[:input {:value (:name state)
:on-change #(dispatch :change-name (aget % "target" "value"))}]])
(defmethod action :change-name
[state value]
;; State here is map, not atom!
(assoc state :name value))
(r/defc ui-app < r/reactive
[state-atom]
(ui-form (r/react state-atom)))
(ns sample.core
(:require [rum.core :as rum]
[sample.components :as components]
[sample.redux :as redux]))
(enable-console-print!)
;; Attach react tree to DOM
(rum/mount (components/ui-app redux/state)
(js/document.getElementById "app"))
;; Dev helper. It touches state when code reloaded to start rerender.
(defn on-js-reload []
(swap! redux/state update-in [:__figwheel_counter] inc))
(ns sample.redux
(:require [cljs.core.async :as a])
(:require-macros [cljs.core.async.macros :refer [go go-loop]]))
(defonce state (atom {:name "World"}))
(defonce actions (a/chan))
;; Components call this function to request state changing.
(defn dispatch
"Dispatch new action. Type should be keyword."
([type] (dispatch type nil))
([type data]
(a/put! actions [type data])))
;; All state changes should be done via this method.
(defmulti action
"Transform state by action. Return updated state."
(fn [state data dispatch action-type] action-type))
;; Start actions pipeline
(go-loop []
(when-let [a (a/<! actions)]
(let [[action-type data] a]
(println "Handle action" action-type)
(swap! state action data dispatch action-type))
(recur)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment