We can set the URL using a string (event dispatch). This will end up calling a function with the same name as the string (an event handler). The function handler can then update the state.
;; state
(def state (atom { :content "" }))
(def session (atom { :page "home" }))
;; handlers
;;
(defn about [] (clojure.core/swap! state assoc :content "About us"))
(defn home [] (clojure.core/swap! state assoc :content "Homepage"))
;; dispatcher
;;
(defn set-url [page] (clojure.core/swap! session assoc :page page))
;; router
;; this basically does something like `(resolve :about)`.
;;
(add-watch session :url-watcher (fn [_ _ _ new_state] ((resolve (symbol (new_state :page))))))
;; usage
@state
;; {:content ""}
(set-url "home")
@state
;; {:content "Homepage"}
(set-url "about")
@state
;; {:content "About us"}
We have two atoms to prevent an infinite loop, since the watcher would otherwise be called when the handlers update the :content
key.