Skip to content

Instantly share code, notes, and snippets.

@NguyenDa18
Last active January 15, 2020 23:16
Show Gist options
  • Save NguyenDa18/8d2285dbef5e17353850030e8c56c92d to your computer and use it in GitHub Desktop.
Save NguyenDa18/8d2285dbef5e17353850030e8c56c92d to your computer and use it in GitHub Desktop.
Clojure Reagent & Reframe

Reagent Notes

  • Usage [reagent.core :as r]

Syntax Quirks

  • [:<> [*components*]] = JSX Fragment for Reagent
  • [:> *Component*] = shorthand for [(r/adapt-react-class *Component*)]
  • [:> *Component* {:variant "some-prop"} "Click me"] = send JSX element properties as a map
  • (js->clj myobj :keywordize-keys true) = parse JSON to Clojure map (I think)

Quick Example

(defn app
  []
  [:<>
   [:> Normalize]
   [:> Button]
   [:div "Plus Ultra!"]])

Almost like Object.assign({}, smth)

(merge 
(js->clj obj :keywordize-keys true)
{:prop1 "overwrite"
  :prop2 "overwrite"
  :prop3 "overwrite"}))

Example

(def my-theme (merge 
                   (js->clj theme :keywordize-keys true)
                   {:black "#243B53"
                    :primary "#27AB83"
                    :modalHeaderBorderColor "white"}))

Re-Frame Notes

  • Usage [re-frame.core :as rf]

Init

(defn app
  []
  [:<>
   [:> ThemeProvider {:theme cheffy-theme}
    [:> Button {:variant "danger"} "click me"]]])
    
(defn ^:dev/after-load start
  []
  ; dispatch init db here, only use dispatch-sync for initial load, we want rest of dispatches to be async: rf/dispatch
  (rf/dispatch-sync [:initialize-db])
  (r/render [app]
            (.getElementById js/document "app")))

Register Event

; like Redux reducer, take :action-type return derived state
(rf/reg-event-db
 :initialize-db
 (fn [_ _]
   initial-app-db))

Dispatch an Event

#(rf/dispatch [:<event type> <params>])

Register Subscription

reg-sub associates a query id with a function that computes that query, like this:

(rf/reg-sub
  :some-query-id  ;; query id (used later in subscribe)
  a-query-fn)     ;; the function which will compute the query

Later, a view function (domino 5) will subscribe to a query like this: (subscribe [:some-query-id]), and a-query-fn will be used to perform the query over the application state.

Each time application state changes, a-query-fn will be called again to compute a new materialised view (a new computation over app-db) and that new value will be given to all view functions which are subscribed to :some-query-id. These view functions will then be called to compute the new DOM state (because the views depend on query results which have changed).

Along this reactive chain of dependencies, re-frame will ensure the necessary calls are made, at the right time.

Here's the code:

(rf/reg-sub
  :time
  (fn [db _]     ;; db is current app state. 2nd unused param is query vector
    (:time db))) ;; return a query computation over the application state

(rf/reg-sub
  :time-color
  (fn [db _]
    (:time-color db)))

Inspect State on Console

  • in console, log re_frame.db.app_db.state
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment