Skip to content

Instantly share code, notes, and snippets.

@souenzzo souenzzo/tiny-om.cljs
Last active Aug 28, 2019

Embed
What would you like to do?
(ns tiny-om.client
(:require ["react" :as r]
[goog.dom :as gdom]
["react-dom" :as r.dom])
(:require [clojure.core.async :as async]))
(defn el
[app type props & children]
(apply r/createElement (name type) (clj->js props) children))
(defn transact!
[{::keys [tx-chan] :as from} tx]
(async/put! tx-chan (assoc from ::tx tx)))
(defn app
[{:as app}]
(let [tx-chan (async/chan)]
(async/go-loop []
(when-let [app (async/<! tx-chan)]
(let [handler! (-> app ::mutations first ::mutation!)]
(try
(handler! app)
(async/>! (-> app ::render-ch) (-> app ::state deref))
(catch :default e
(.error js/console e))))
(recur)))
(assoc app
::render-ch (async/chan)
::tx-chan tx-chan
::state (atom {:n 0}))))
(def component-n
{::query [:n]
::render (fn [this {:keys [n]}]
(el this :div {}
(el this :div {} (str "n: " n))
(el this :button {:onClick #(transact! this `[(inc ~{})])} "+")))})
(def mutation-inc
{::sym `inc
::mutation! (fn [{::keys [state]}]
(.log js/console @state)
(swap! state update :n inc))})
(defn element
[app]
(let [render (-> app ::components first ::render)
state (-> app ::state)
chan (-> app ::render-ch)]
(r/createElement (fn []
(let [[st set-state] (r/useState @state)]
(async/go-loop []
(when-let [st (async/<! chan)]
(set-state st)
(recur)))
(render app st))))))
(defn main []
(let [app (app {::components [component-n]
::mutations [mutation-inc]})]
(r.dom/render
(element app)
(gdom/getElement "app"))))
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.