Skip to content

Instantly share code, notes, and snippets.

@Hendekagon
Last active September 24, 2018 08:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Hendekagon/4671b105774bf31f1240a2f0c25febb2 to your computer and use it in GitHub Desktop.
Save Hendekagon/4671b105774bf31f1240a2f0c25febb2 to your computer and use it in GitHub Desktop.
A note on Clojurescript React interfaces

Let's read the getting-started guides for the 3 top Clojurescript React interfaces:

https://reagent-project.github.io/

https://github.com/tonsky/rum/

https://github.com/omcljs/om/wiki/Quick-Start-%28om.next%29

What do they have in common ? Taking the Reagent example:

(ns example
  (:require [reagent.core :as r]))

(def click-count (r/atom 0))

(defn counting-component []
  [:div
   "The atom " [:code "click-count"] " has value: "
   @click-count ". "
   [:input {:type "button" :value "Click me!"
            :on-click #(swap! click-count inc)}]])
                          ^   
                          |
                     this pattern

Yes, it's mixing application logic in UI code.

Let's recall how we got here:

https://developer.apple.com/library/content/documentation/General/Conceptual/DevPedia-CocoaCore/MVC.html

Now, we don't have to be religious about these things but I think we should keep the top part of the flow in the MVC triangle -- i.e. the separation of concerns. The bottom part can be shortcutted in FRP without losing anything, but the top part is worth keeping. Loose-coupling is usually a good idea.

Why ?

  • easier to reason about cause and effect if view code only deals with rendering and dispatching events (messages)
  • decoupling events from their actions makes code easier to evolve because we can re-map those causes and effects as the mappings are explicit
  • we can have arbitrary mappings between multiple events and actions, which makes it easy to make the same action be triggered by either keyboard shortcuts, mouse clicks on buttons or server events
  • these mappings can be changed at runtime rather than being hardcoded
  • we can test the application logic without the UI, because all app-state-changing functions are pure functions of state and an event, which we can test separately
  • we can capture streams of events and later replay them to test the UI
  • we can test the application with simulated streams of UI events
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment