Last active
February 10, 2017 09:44
-
-
Save jeroenvandijk/9cbf0048cd87f5c416ee8cab9c52ecb7 to your computer and use it in GitHub Desktop.
Rum reconciling like
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns adgoji.rum.reconciler.example | |
(:require [rum.core :as rum] | |
[adgoji.rum.subscriptive :as sub])) | |
(enable-console-print!) | |
(println "This text is printed from src/adgoji.rum.reconciler/core.cljs. Go ahead and edit it and see reloading in action.") | |
;; define your app data so that it doesn't get over-written on reload | |
(rum/defc hello-world1 < sub/subscriptive [pub] | |
[:div | |
[:h1 (str "hi 2" (sub/subscribe pub :example))] | |
[:p | |
[:a | |
{ :on-click (fn [] (sub/publish! pub [:example2 "linked clicked"]))} | |
"link clicked!"]]]) | |
(rum/defc hello-world2 < sub/subscriptive [pub] | |
[:h1 (str "hi 2" (sub/subscribe pub :example2))]) | |
(declare reconciler counter) | |
(when-not counter | |
(js/setInterval (fn [] | |
(sub/publish! reconciler [:example (str "counter " (swap! counter inc))])) | |
1000)) | |
(defonce counter (atom 10)) | |
(defonce reconciler (atom {})) | |
(rum/defc root [pub] | |
[:div | |
(hello-world1 pub) | |
(hello-world2 pub)]) | |
(rum/mount (root reconciler) (. js/document (getElementById "app"))) | |
(defn on-js-reload [] | |
;; optionally touch your app-state to force rerendering depending on | |
;; your application | |
;; (swap! app-state update-in [:__figwheel_counter] inc) | |
) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns adgoji.rum.subscriptive | |
(:require [rum.core :as rum])) | |
(def ^:private ^:dynamic *subscriptions*) | |
(def ^:private ^:dynamic *subscription-results*) | |
(defprotocol IPublisher | |
(add-subscription [publisher query id callback]) | |
(remove-subscription [publisher query id]) | |
(publish! [publisher data])) | |
(extend-type cljs.core.Atom | |
IPublisher | |
(add-subscription [publisher query id callback] | |
(add-watch publisher [query id] | |
(fn [_ _ old-state new-state] | |
(let [query-value (get new-state query)] | |
(when-not (= (get old-state query) query-value) | |
(callback (first query-value))))))) | |
(remove-subscription [publisher query id] | |
(remove-watch publisher [query id])) | |
(publish! [this [query data]] | |
(swap! this assoc query [data (random-uuid)]))) | |
(def subscriptive | |
"Mixin. Works in conjunction with `rum.core/subscribe. Needs to be wrapped under another | |
subscriptive component or under root.`" | |
{:init | |
(fn [state props] | |
(assoc state | |
:rum.subscriptive/key (random-uuid) | |
:rum.subscriptive/results (volatile! {}))) | |
:wrap-render | |
(fn [render-fn] | |
(fn [state] | |
(binding [*subscriptions* (volatile! #{}) | |
*subscription-results* (:rum.subscriptive/results state)] | |
(let [comp (:rum/react-component state) | |
old-subscriptions (:rum.subscriptive/subscriptions state #{}) | |
[dom next-state] (render-fn state) | |
new-subscriptions @*subscriptions* | |
key (:rum.subscriptive/key state)] | |
(doseq [[publisher qyr :as k] old-subscriptions] | |
(when-not (contains? new-subscriptions k) | |
(remove-subscription publisher qyr key))) | |
(doseq [[publisher qyr :as k] new-subscriptions] | |
(when-not (contains? old-subscriptions k) | |
(add-subscription publisher qyr key | |
(fn [res] | |
(vswap! (:rum.subscriptive/results state) assoc k res) | |
(rum/request-render comp))))) | |
[dom (assoc next-state | |
:rum.subscriptive/subscriptions new-subscriptions)])))) | |
:will-unmount | |
(fn [state] | |
(let [key (:rum.subscriptive/key state)] | |
(doseq [[publisher query] (:rum.subscriptive/subscriptions state)] | |
(remove-subscription publisher query key))) | |
(dissoc state | |
:rum.subscriptive/subscriptions | |
:rum.subscriptive/key | |
:rum.subscriptive/results))}) | |
(defn subscribe | |
"Works in conjunction with `rum.core/subscriptive` mixin. Use this function instead of | |
`deref` inside render, and your component will subscribe to changes happening | |
to the derefed atom." | |
[publisher qry] | |
(let [k [publisher qry]] | |
(assert (and *subscriptions* *subscription-results*) "rum.core/subscribe is only supported in conjunction with rum.core/subscriptive") | |
(vswap! *subscriptions* conj k) | |
(get @*subscription-results* k :not-available-yet))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment