Skip to content

Instantly share code, notes, and snippets.

@runexec
Last active January 23, 2018 17:09
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save runexec/6efb322f29fc790a98a1 to your computer and use it in GitHub Desktop.
Save runexec/6efb322f29fc790a98a1 to your computer and use it in GitHub Desktop.
Om and React.js Does It Better

Om and React.js Does It Better

A hopefully short and concise explanation as to how Om/React.js works. This probably isn't for you if you already use ClojureScript or Om.

The front end and JavaScript God known as David Nolen created a ClojureScript library called Om. Om is a front end library that uses React.js and makes web MVC not just obsolete, but an anti-pattern.

In Om there's just the data and the view.

  1. data =>

  2. is different or unset? =>

  3. if true, render dom.

Parts of the view is updated only when the data changes.

  1. original-state = array("name1", "name2") =>

  2. event triggered =>

  3. new-state = array("name1", "name2", "name3") =>

  4. is different or unset? =>

  5. if true, render dom

If not MVC, what is it? It's parent-data.

Let's say you have an application for managing cars. This might be the initial state of your application.

(defonce app-sate
  (atom {:cars
         [{:id 1 :car "old red" :slot 10}
          {:id 80 :car "new blue" :slot 40}]}))

Let's say you have a view called parking-space. (using om tools)

;; car - value from the car keyword in the app state
(defcomponent parking-space [car owner]
  (render
   [_]
   (let [{:keys [car id]} car]
     
     ;; <li>...</li>
     (dom/li
      
      ;; tag attributes
      {:class "parking space"
       :id (str "parking-space-" (gensym))}
      
      ;; <h2>..</h2>
      (dom/h2 car)
      
      ;; <a id="" href="" onClick="">remove</a>
      (let [html-id (str "example-" id)
            href (str "#" html-id)
            remove (fn [& _]
                     (swap! app-state
                            update-in
                            [:cars]
                            (fn [cars]
                              (remove #(-> % :id (= id)) cars))))]
                                      
        (dom/a {:id html-id
                :href href
                :on-click remove} "remove"))))))

Now let's say you have a parking lot. (using om tools)

;; app - application state
(defcomponent parking-lot [app owner]
  (render
   [_]

   ;; <ul>..</ul> - unordered list
   (dom/ul

    ;; tag attributes
    {:class "parking lot"
     :id "parking-lot"}

    ;; array_map(parkingSpace, carsArray);
    (om/build-all parking-space (:cars app)))))

Where should this parking lot go?

;; set React.js parking-lot function
(defn main []
  (om/root
   (fn [app owner]
     (parking-lot app owner))
   app-state
   {:target (. js/document
               (getElementById "parking-lot"))}))

All you have to do now is modify the data and the view takes care of the rest

That's literally it. You can think of it this way =>

  1. Create bindings

  2. Add/Remove/Update data

  3. Relax.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment