Skip to content

A Larger App

mike-thompson-day8 edited this page May 2, 2015 · 22 revisions

Simpler Apps

To build a re-frame app, you:

  • design your app's data structure (data layer)
  • write and register subscription functions (query layer)
  • write Reagent component functions (view layer)
  • write and register event handler functions (control layer and/or state transition layer)

For simpler apps, you should put code for each layer into separate files:

src
├── core.cljs         <--- entry point, plus history
├── db.cljs           <--- data related - schema, validation, etc  (data layer)
├── subs.cljs         <--- subscription handlers  (query layer)
├── views.cljs        <--- reagent components (view layer)
└── handlers.cljs     <--- event handlers (control/update layer)

For further guidance, look at the todomvc example .

Larger Apps

Assuming your larger apps has multiple "panels" or "views" which are relatively independent, you might use this structure:

src
├── panel1
   ├── db.cljs           <--- schema, validation, etc  (data layer)
   ├── subs.cljs         <--- subscription handlers  (query layer)
   ├── views.cljs        <--- reagent components (view layer)
   └── handlers.cljs     <--- event handlers (control/update layer)
├── panel2
   ├── db.cljs           <--- schema, validation. etc  (data layer)
   ├── subs.cljs         <--- subscription handlers  (query layer)
   ├── views.cljs        <--- reagent components (view layer)
   └── handlers.cljs     <--- event handlers (control/update layer)
.
.
└── panelN

What About Navigation?

How do I switch between different panels of a larger app?

Your app-db could have :active-panel key containing an id for the panel being displayed.

When the user does something navigation-ish (selects a tab, a dropdown or something which changes the active panel), then the associated dispatch looks like this:

(dispatch [:set-active-panel :panel1])

A high level reagent view has a subscription to :active-panel and will switch to the associated panel.

(defn panel1
   []
   [:div  {:on-click #(dispatch [::set-active-panel :panel2])}
          "Here" ])

(defn panel2
   []
   [:div "There"])

(defn high-level-view
   []
   (let [active  (subscription [:active-panel])]
      (fn []
         [:div
             [div.title   "Heading"]
            (condp = @active                ;; or you could look up in a map
               :panel1   [panel1]
               :panel2   [panel2])])))