Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Redux with basically no effort in clojurescript, plus core.async to handle asynchronous actions
(ns reduxish.state-tools
(:require-macros [cljs.core.async.macros :refer [go go-loop]])
(:require [cljs.core.async.impl.protocols :refer [WritePort ReadPort]]
[cljs.core.async :refer [<!]]))
(defn channel?
"A predicate that determines if the provided thing is a core.async channel"
[ch]
(and (satisfies? WritePort ch) (satisfies? ReadPort ch)))
(defn dispatch!
"Dispatch an action. Not to be used on its own"
[reducer state value]
(if (channel? value)
(go (loop []
(when-let [message (<! value)]
(<! (dispatch! state reducer message))
(recur))))
(go (prn state reducer value) (swap! state reducer value))))
(defn action
"Flux-standard-action action creator fn"
([type] { :type type})
([type payload] { :type type :payload payload}))
(defn dispatch-on-type
"Use this to make reducers quickly!"
[_ {:keys [type]}] type)
(defn make-store
"Creates a new redux-ish store"
[reducer]
(let [state (atom (reducer))]
{:state state
:dispatch! (partial dispatch! reducer state)}))
;; Create a reducer that increments or decrements a value
(defmulti reducer dispatch-on-type)
(defmethod reducer :default [] 0)
(defmethod reducer :increment [state action] (inc state))
(defmethod reducer :decrement [state action] (dec state))
(let [{:keys [dispatch! state]} (make-store reducer)]
(go
(<! (dispatch! (action :increment)))
(<! (dispatch! (action :increment)))
(println @state)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.