Created
February 7, 2020 15:17
-
-
Save frankiesardo/d2d3b08d56cb4a8ee33ffd54ae2d26b5 to your computer and use it in GitHub Desktop.
stop.worry/love-js
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 stop-worry.core | |
(:require ["react" :as react :rename {createElement $}] | |
["react-dom" :as dom] | |
[goog.object :as obj] | |
[cljs.core.async :as async])) | |
(extend-type object | |
ILookup | |
(-lookup | |
([o k] (obj/get o (name k))) | |
([o k not-found] (obj/get o (name k) not-found)))) | |
(defonce app-atom | |
(atom {:parent | |
{:name "Dad"} | |
:children | |
[{:name "Alice"} | |
{:name "Bob"} | |
{:name "Charlie"}]})) | |
(defonce app-chan (async/chan)) | |
(defn useAtom [a] | |
(let [[state update-state] (react/useState @a)] | |
(react/useEffect | |
(fn [] | |
(add-watch a :use-atom | |
(fn [_ _ _ new-state] | |
(update-state new-state))) | |
#(remove-watch a :use-atom)) | |
#js [a]) | |
state)) | |
(defmulti handle-event (fn [atom event-name & _args] event-name)) | |
(defmethod handle-event ::rename [atom _ index name] | |
(swap! atom assoc-in [:children index :name] (apply str (shuffle name)))) | |
(defn eq [a b] | |
(= (:state a) (:state b))) | |
(defn Child* [{:keys [chan state]}] | |
(let [{:keys [name index]} state] | |
(js/console.log "Rendering Child " name) | |
($ "div" nil | |
($ "h3" nil "I'm a child component") | |
($ "span" nil "My name is: " name | |
($ "button" #js {:onClick #(async/put! chan [::rename index name])} "Rename me!"))))) | |
(def Child (react/memo Child* eq)) | |
(defn Parent* [{:keys [chan state]}] | |
(let [{:keys [parent children]} state] | |
(js/console.log "Rendering Parent") | |
($ "div" nil | |
($ "h2" nil "I'm the parent component") | |
($ "div" nil "My name is: " (get parent :name)) | |
(for [[i child] (map-indexed vector children)] | |
($ Child #js {:key i :chan chan :state (assoc child :index i)}))))) | |
(def Parent (react/memo Parent* eq)) | |
(defn App [] | |
(let [state (useAtom app-atom)] | |
(react/useEffect | |
(fn [] | |
(let [loop (async/go-loop [] | |
(let [event (async/<! app-chan)] | |
(js/console.log "--- Event received ---") | |
(apply handle-event app-atom event)) | |
(recur))] | |
#(async/close! loop))) | |
#js []) | |
(js/console.log "Rendering App") | |
($ "div" nil | |
($ "h1" nil "This is a sample app") | |
($ Parent #js {:chan app-chan :state state})))) | |
(defn start [] | |
(dom/render ($ App) (js/document.getElementById "app"))) | |
(defn ^:export init [] | |
(start)) | |
(defn stop [] | |
(js/console.log "stop")) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment