0

I am trying to create SPA application with Reagent. How I can define default page/component? As I understand it, I should save current page in state atom. But I can't define it if I change state in home page. For example, in this code home cannot be resolved (row 1):

(defonce app-state (atom {:current-page (home)}))

(defn second-page []
  [:p 2])

(defn home []
  [:div
   [:p 1]
   [:input {:type "button" :value "Click!"
            :on-click #(swap! app-state second-page)}]])

(defn hello-world []
  [:div
   [:input {:type "button" :value "Home" :on-click #(swap! app-state home)}]
   (:current-page @app-state)
   [:h3 "footer"]])

(reagent/render-component [hello-world]
                          (. js/document (getElementById "app")))
VsSekorin
  • 355
  • 1
  • 3
  • 17

2 Answers2

2

There are a few ways you can solve this issue. One approach would be to create a map called pages like so

(def pages {:home home
            :second second-page
            ....}

and then use the key name in the state atom i.e.

(defonce app-state (atom {:current-page :home})

Because you are just storing a keyword, there is no need for forward delarations as keywords evaluate to themselves. Then in your code, you would use the value for :current-page to lookup the compoonent from the pages map

defn hello-world []
  [:div
   [:input {:type "button" :value "Home" :on-click #(swap! app-state home)}]
   ((:current-page @app-state) pages)
   [:h3 "footer"]])

You may also find things like secretary useful as an example of one way to generalise this sort of idea.

Tim X
  • 4,158
  • 1
  • 20
  • 26
1

Just use declare to put placeholders for home and second-page before the atom:

(declare home second-page)

(defonce app-state (atom {:current-page home}))

Be sure to always keep a browser tab open to The Clojure CheatSheet. See also this answer for more details on the workings of Clojure's var feature.

Alan Thompson
  • 29,276
  • 6
  • 41
  • 48
  • Thanks for the answer. But in your case `app-state` is undefined in line `:on-click #(swap! app-state second-page)}]`. Can you give me please a example how I can use `declare` for this problem? I should use `(declare app-state)` or `(declare home)`? – VsSekorin Jul 31 '19 at 12:12