Skip to content

Instantly share code, notes, and snippets.

@jellea
Last active February 3, 2016 10:54
Show Gist options
  • Save jellea/257633d5ceb962cb3cac to your computer and use it in GitHub Desktop.
Save jellea/257633d5ceb962cb3cac to your computer and use it in GitHub Desktop.
Minimal Redux implementation in clojurescript. Two versions.
(def initial-state {:counter 0})
(defonce !state (r/atom initial-state))
(defonce !actions (atom []))
(defprotocol Action
(reducer [action state]))
(defn dispatch! [action]
(swap! !actions conj action))
;; Listen for new action and reduce into new-state
(add-watch !actions :reduce
(fn [_ _ _ new-state]
(let [new-action (last new-state)]
(swap! !state #(reducer new-action %)))))
;; Roll your own Action:
;;
;; (defrecord IncrementCounter [num])
;;
;; (extend-protocol Action
;; IncrementCounter
;; (reducer [{:keys [num]} state]
;; (update state :counter #(+ % num))))
;;
;; Dispatch Action: (dispatch! (->IncrementCounter 2))
;; TODO: Selectors: http://rackt.org/redux/docs/recipes/ComputingDerivedData.html
;; Would reagents cursors or track do the trick?
(def initial-state {:counter 0})
(defonce !state (r/atom initial-state))
(defonce !actions (atom []))
(defmulti Action (fn [action state] (:type action)))
(defn dispatch! [action]
(swap! !actions conj action))
;; Listen for new action and reduce into new-state
(add-watch !actions :reduce
(fn [_ _ _ new-state]
(let [new-action (last new-state)]
(swap! !state #(Action new-action %)))))
(defn rereduce
"Reduce past actions over state to get a fresh copy. As all actions
are stored as data, changes in actions will be projected on state.
Useful for live reload."
[]
(reset! !state (reduce #(Action %2 %1) initial-state @!actions)))
;; Roll your own Action:
;;
;; (defmethod Action :Increment [{:keys [num]} state]
;; (update state :counter #(- % num)))
;;
;;
;; Dispatch Action:
;;
;; (dispatch! {:type :Increment :num 10})
(ns redux-test.reagent-example
(:require [reagent.core :as r]))
(enable-console-print!)
;; MODEL
(def initial-state {:counter 0
:list []})
(defonce !state (r/atom initial-state))
(defonce !actions (r/atom []))
(defn dispatch! [action]
(swap! !actions conj action))
(defmulti Action (fn [action state] (:type action)))
(add-watch !actions :reduce
(fn [_ _ _ new-state]
(let [new-action (last new-state)]
(swap! !state #(Action new-action %)))))
(defn rereduce
"Reduce past actions over state to get a fresh copy. As all actions
are stored as data, changes in actions will be projected on state."
[]
(reset! !state (reduce #(Action %2 %1) initial-state @!actions)))
;; ACTIONS
(defmethod Action :Change [_ state]
(update state :list #(conj % "more")))
(defmethod Action :Increment [{:keys [num]} state]
(update state :counter #(- % num)))
;; VIEW
(defn root []
[:div
[:pre "state: " (str @!state)]
[:pre "actions: " (str @!actions)]
[:button {:on-click #(dispatch! {:type :Change})} "more"]
[:button {:on-click #(dispatch! {:type :Increment :num 10})} "+10"]])
(r/render [root] (js/document.getElementById "app"))
(defn on-js-reload
"Hook for figwheel reload"
[]
(rereduce))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment