Refactor sidebar to make it reloadable without losing state

This commit is contained in:
Jeremy Dormitzer 2018-02-17 09:27:26 -05:00
parent 867d8fab56
commit 2702283490
No known key found for this signature in database
GPG Key ID: 04F17C0F5A32C320

View File

@ -84,30 +84,34 @@
item item
(get-in-item (nth (:children item) fdepth) rdepth))) (get-in-item (nth (:children item) fdepth) rdepth)))
(defn model (defonce state
"Returns initial sidebar state" (atom {:item nil
[] :hits nil
{:item nil :depth []
:hits nil :loading false}))
:depth []
:loading false})
(defn update-state (defn update-state
"Given a message and the old state, returns the new state" "Given a message, returns the new state"
[msg state] [msg]
(case (:type msg) (case (:type msg)
:got-item (-> state :got-item (swap! state
(assoc :item (:item msg)) #(-> %
(assoc :loading false)) (assoc :item (:item msg))
:got-hits (-> state (assoc :loading false)))
(assoc :hits (:hits msg)) :got-hits (swap! state
(assoc :loading false)) #(-> %
:enq-depth (assoc state :depth (conj (:depth state) (:index msg))) (assoc :hits (:hits msg))
:deq-depth (assoc state :depth (assoc :loading false)))
(subvec (:depth state) 0 (- (count (:depth state)) 1))) :enq-depth (swap! state
:clear-item (assoc state :item nil) #(assoc % :depth (conj (:depth @state) (:index msg))))
:loading (assoc state :loading (:loading msg)) :deq-depth (swap! state
state)) #(assoc % :depth
(subvec (:depth @state) 0 (- (count (:depth @state)) 1))))
:clear-item (swap! state
#(assoc % :item nil))
:loading (swap! state
#(assoc % :loading (:loading msg)))
@state))
(defn view (defn view
"Given a callback to dispatch an update message and the sidebar state, returns the sidebar DOM" "Given a callback to dispatch an update message and the sidebar state, returns the sidebar DOM"
@ -244,14 +248,17 @@
(dispatch-message (dispatch-message
{:type :clear-item}))))))) {:type :clear-item})))))))
(declare run-render-loop)
(defn dispatch-message [msg]
(let [new-state (update-state msg)]
(run-render-loop new-state)))
(defn run-render-loop (defn run-render-loop
"Runs the model-update-view loop" "Runs the model-update-view loop"
[state] [state]
(let [dispatch-message (fn [msg] (render (view dispatch-message state))
(let [new-state (update-state msg state)] (handle-events dispatch-message state))
(run-render-loop new-state)))]
(render (view dispatch-message state))
(handle-events dispatch-message state)))
(defn fetch-hits (defn fetch-hits
"Fetch hits in the Algolia API matching the URL" "Fetch hits in the Algolia API matching the URL"
@ -267,12 +274,12 @@
(defn init (defn init
"Initializes the sidebar" "Initializes the sidebar"
[] []
(let [initial-state (update-state {:type :loading :loading true} (model))] (let [initial-state (update-state {:type :loading :loading true})]
(run-render-loop initial-state) (run-render-loop initial-state)
(go (-> (fetch-hits) (go (-> (fetch-hits)
(<!) (<!)
(#(update-state {:type :got-hits (#(update-state {:type :got-hits
:hits %} initial-state)) :hits %}))
(run-render-loop))))) (run-render-loop)))))
(init) (init)