Skip to content

Instantly share code, notes, and snippets.

@nhusher
Last active September 18, 2018 17:28
Show Gist options
  • Save nhusher/7e687e6f4e999b23b559bcd1afbc3c5a to your computer and use it in GitHub Desktop.
Save nhusher/7e687e6f4e999b23b559bcd1afbc3c5a to your computer and use it in GitHub Desktop.
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