Created
March 30, 2020 10:41
-
-
Save frankiesardo/77905fef92311f688a306ccdb28e1766 to your computer and use it in GitHub Desktop.
reducer-context.core
This file contains 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 reducer-context.core | |
(:require ["react" :as react :rename {createElement $}] | |
["react-dom" :as dom] | |
[goog.object :as obj])) | |
(extend-type object | |
ILookup | |
(-lookup | |
([o k] (obj/get o (name k))) | |
([o k not-found] (obj/get o (name k) not-found)))) | |
(def initial-state | |
{:parent | |
{:name "Dad"} | |
:children | |
[{:name "Alice"} | |
{:name "Bob"} | |
{:name "Charlie"}]}) | |
(defmulti reducer (fn [state {:keys [type payload] :as action}] type)) | |
(defmethod reducer ::rename [state {{:keys [index]} :payload}] | |
(update-in state [:children index :name] #(apply str (shuffle %)))) | |
(defn reducer* [state action] (reducer state action)) | |
(defn eq [a b] | |
(= (:state a) (:state b))) | |
(def DispatchContext (react/createContext)) | |
(defn Child* [{:keys [state]}] | |
(let [{:keys [name index]} state | |
dispatch! (react/useContext DispatchContext) | |
action {:type ::rename :payload {:index index}}] | |
(js/console.log "Rendering Child " name) | |
($ "div" nil | |
($ "h3" nil "I'm a child component") | |
($ "span" nil "My name is: " name | |
($ "button" #js {:onClick #(dispatch! action)} "Rename me!"))))) | |
(def Child (react/memo Child* eq)) | |
(defn Parent* [{:keys [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 :state (assoc child :index i)}))))) | |
(def Parent (react/memo Parent* eq)) | |
(defn App [] | |
(let [[state dispatch!] (react/useReducer reducer* initial-state)] | |
($ DispatchContext.Provider #js {:value dispatch!} | |
($ Parent #js {: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