SlideShare a Scribd company logo
High Performance Web UI's with
Om and React
LambdaJam - Brisbane, 2014
Leonardo Borges
@leonardo_borges
www.leonardoborges.com
www.thoughtworks.com
About
‣ ThoughtWorker
‣ Functional Programming & Clojure
advocate
‣ Founder of the Sydney Clojure User
Group
‣ Currently writing “Clojure Reactive
Programming”
Functional Programming
is on the rise
And that makes us happy
However if you do client-side web
development, you’re out of luck
Because Javascript…
[1,3,5].map(parseInt);!
// [1, NaN, NaN]!
There are options
Today we’ll see one of them:
Clojurescript
What we’ll see
‣ An Overview of React and how it enables fast rendering
‣ Meet Om, a ClojureScript interface to React
‣ Boosting React’s rendering performance with immutable data structures
‣ A simple demo featuring “data binding” and undo functionality
React
‣ Created by Facebook for building user interfaces
‣ The V in MVC
‣ Self-contained components
‣ Doesn’t make assumptions about your stack - can be used with anything
Self-contained components
‣ React combines display logic and DOM generation
‣ Components are themselves loosely coupled
‣ The whole app is re-rendered on every update
‣ Virtual DOM
‣ Efficient diff algorithm
Efficient diff algorithm
‣ Creates a virtual version of the DOM
‣ As the application state changes new DOM trees are generated
‣ React diffs the trees and computes the minimal set of changes
‣ Finally it applies the changes to the real DOM
A simple React component
var HelloMessage = React.createClass({!
displayName: 'HelloMessage',!
render: function() {!
return React.DOM.div(null, "Hello ", this.props.name);!
}!
});!
!
React.renderComponent(!
HelloMessage( {name:"John"} ), mountNode);
No literals?
A simple React component (using the
JSX pre-processor)
var HelloMessage = React.createClass({!
render: function() {!
return <div>Hello {this.props.name}</div>;!
}!
});!
!
React.renderComponent(!
<HelloMessage name="John" />, mountNode);
React components are functions from
application state to a DOM tree
Now let’s take a leap and look at the same
component, written in Om
A simple Om component
(def app-state (atom {:name "Leo"}))!
!
(defn hello-message [app owner]!
(reify om/IRender!
(render [_]!
(dom/div nil!
(str "Hello " (:name app))))))!
!
!
(om/root hello-message app-state!
{:target (. js/document (getElementById "hello"))})!
Om/React’s component lifecycle
IWillMountIInitState IShouldUpdate
IRender
IRenderState
IShouldUpdate
‣ Called on app state changes but before rendering
‣ This is where React uses its fast diff algorithm
‣ Om components implement the fastest algorithm possible: a simple
reference equality check
‣ Generally, you won’t have to implement this
IInitState & IRenderState
‣ Initialise component local state using IInitState
‣ Use IRenderState to work with it and render the component
IInitState & IRenderState
(defn counter [app owner]!
(reify!
om/IInitState!
(init-state [_]!
{:clicks 0})!
om/IRenderState!
(render-state [_ state]!
(dom/div nil!
(str "Clicks " (:clicks state))!
(dom/button #js {:onClick!
#(om/set-state! owner :clicks (inc (:clicks state)))}!
"Click me!")))))!
!
(om/root counter (atom {})!
{:target (. js/document (getElementById "app"))})!
IRender
‣ Same as IRenderState…
‣ …except it doesn’t depend on the component local state to render
IRender
(def app-state (atom {:name "Leo"}))!
!
(defn hello-message [app owner]!
(reify om/IRender!
(render [_]!
(dom/div nil!
(str "Hello " (:name app))))))!
!
!
(om/root hello-message app-state!
{:target (. js/document (getElementById "hello"))})!
A larger example
A larger example
A reusable editable component
(defn editable [text owner]!
(reify!
om/IInitState!
(init-state [_]!
{:editing false})!
om/IRenderState!
(render-state [_ {:keys [editing]}]!
(dom/li nil!
(dom/span #js {:style (display (not editing))} (om/value text))!
(dom/input!
#js {:style (display editing)!
:value (om/value text)!
:onChange #(handle-change % text owner)!
:onKeyPress #(when (== (.-keyCode %) 13)!
(commit-change text owner))!
:onBlur (fn [e] (commit-change text owner))})!
(dom/button!
#js {:style (display (not editing))!
:onClick #(om/set-state! owner :editing true)}!
"Edit")))))!
From https://github.com/swannodette/om/wiki/Basic-Tutorial
A reusable editable component
(defn editable [text owner]!
(reify!
om/IInitState!
(init-state [_]!
{:editing false})!
om/IRenderState!
(render-state [_ {:keys [editing]}]!
(dom/li nil!
(dom/span #js {:style (display (not editing))} (om/value text))!
(dom/input!
#js {:style (display editing)!
:value (om/value text)!
:onChange #(handle-change % text owner)!
:onKeyPress #(when (== (.-keyCode %) 13)!
(commit-change text owner))!
:onBlur (fn [e] (commit-change text owner))})!
(dom/button!
#js {:style (display (not editing))!
:onClick #(om/set-state! owner :editing true)}!
"Edit")))))!
From https://github.com/swannodette/om/wiki/Basic-Tutorial
A reusable editable component
(defn editable [text owner]!
(reify!
om/IInitState!
(init-state [_]!
{:editing false})!
om/IRenderState!
(render-state [_ {:keys [editing]}]!
(dom/li nil!
(dom/span #js {:style (display (not editing))} (om/value text))!
(dom/input!
#js {:style (display editing)!
:value (om/value text)!
:onChange #(handle-change % text owner)!
:onKeyPress #(when (== (.-keyCode %) 13)!
(commit-change text owner))!
:onBlur (fn [e] (commit-change text owner))})!
(dom/button!
#js {:style (display (not editing))!
:onClick #(om/set-state! owner :editing true)}!
"Edit")))))!
From https://github.com/swannodette/om/wiki/Basic-Tutorial
The speakers view
(defn speakers-view [app owner]!
(reify!
om/IRender!
(render [_]!
(dom/div nil!
(dom/div #js {:id "speakers"!
:style #js {:float "left"}}!
(dom/h2 nil "Speakers")!
(dom/button #js {:onClick undo} "Undo")!
(dom/button #js {:onClick reset-app-state} "Reset")!
(apply dom/ul nil!
(om/build-all speaker-view (speakers app)!
{:shared {:app-state app}})))!
(om/build speaker-details-view app)))))
This is how you build
components
The Sessions view
Same deal as before
(defn sessions-view [app owner]!
(reify!
om/IRender!
(render [_]!
(dom/div #js {:id "sessions"}!
(dom/h2 nil "Sessions")!
(apply dom/ul nil!
(map #(om/build editable %) (vals (:sessions
app))))))))!
Apps can have multiple roots
(om/root speakers-view app-state!
{:target (. js/document (getElementById "speakers"))})!
!
(om/root sessions-view app-state!
{:target (. js/document (getElementById "sessions"))})!
You can have multiple “mini-apps” inside your main app
Makes it easy to try Om in a specific section/feature
What about “undo” and “reset”?
Implementing undo
(def app-state (atom speaker-data))!
(def app-history (atom [@app-state]))!
!
(add-watch app-state :history!
(fn [_ _ _ n]!
(when-not (= (last @app-history) n)!
(swap! app-history conj n))!
(let [c (count @app-history)]!
(prn c " Saved items in app history"))))!
!
(defn undo []!
(when (> (count @app-history) 1)!
(swap! app-history pop)!
(reset! app-state (last @app-history))))!
Implementing reset
(defn reset-app-state []!
(reset! app-state (first @app-history))!
(reset! app-history [@app-state]))!
Om/React components are functions from state to
DOM trees
With immutable data structures we can access
every version of the application state
So we simply update the application state, causing
the components to get re-rendered
A bit of live coding
Summary
‣ With Om, you’re not using a crippled template language, you can
leverage all of Clojurescript (including other DOM libraries)
‣ Rendering and display logic are inevitably coupled. Om/React
acknowledges that a bundles them in components
‣ The whole app is re-rendered on every state change, making it easier to
reason about
‣ This is efficient thanks to immutable data structures
Summary
‣ Clojurescript also provides a better development experience with a
powerful browser REPL much like what you’d get with Clojure on the JVM
‣ Source maps are here today
‣ Bottom line is that Clojurescript is a serious contender
References
‣ Code: https://github.com/leonardoborges/lambdajam-2014-om-talk
‣ React documentation: http://facebook.github.io/react/
‣ Om documentation: https://github.com/swannodette/om/wiki/
Documentation#build
‣ Basic Tutorial: https://github.com/swannodette/om/wiki/Basic-Tutorial
Thanks!
Questions?
Leonardo Borges
@leonardo_borges
www.leonardoborges.com
www.thoughtworks.com

More Related Content

PDF
React.js & Om: A hands-on walkthrough of better ways to build web UIs
Adam Solove
 
PDF
React JS and why it's awesome
Andrew Hull
 
PDF
ReactJS
Kamlesh Singh
 
PPTX
REACT.JS : Rethinking UI Development Using JavaScript
Deepu S Nath
 
PDF
Introduction to Redux
Ignacio Martín
 
PDF
Promise pattern
Sebastiaan Deckers
 
PDF
JavaScript promise
eslam_me
 
PDF
JavaScript Promises
Tomasz Bak
 
React.js & Om: A hands-on walkthrough of better ways to build web UIs
Adam Solove
 
React JS and why it's awesome
Andrew Hull
 
ReactJS
Kamlesh Singh
 
REACT.JS : Rethinking UI Development Using JavaScript
Deepu S Nath
 
Introduction to Redux
Ignacio Martín
 
Promise pattern
Sebastiaan Deckers
 
JavaScript promise
eslam_me
 
JavaScript Promises
Tomasz Bak
 

What's hot (20)

PDF
Intro to React
Troy Miles
 
PDF
Callbacks, promises, generators - asynchronous javascript
Łukasz Kużyński
 
PDF
Integrating React.js with PHP projects
Ignacio Martín
 
PDF
React.js or why DOM finally makes sense
Eldar Djafarov
 
PDF
Avoiding callback hell with promises
TorontoNodeJS
 
PDF
Discover React
Massimo Iacolare
 
PPTX
Avoiding Callback Hell with Async.js
cacois
 
PDF
History of jQuery
jeresig
 
PDF
React
중운 박
 
PDF
Mobile Day - React Native
Software Guru
 
PDF
JavaScript - From Birth To Closure
Robert Nyman
 
PDF
$q and Promises in AngularJS
a_sharif
 
PDF
Going fullstack React(ive) - Paulo Lopes - Codemotion Amsterdam 2017
Codemotion
 
PDF
Difference between java script and jquery
Umar Ali
 
PDF
Containers & Dependency in Ember.js
Matthew Beale
 
PPTX
The Promised Land (in Angular)
Domenic Denicola
 
PDF
Workshop 12: AngularJS Parte I
Visual Engineering
 
PDF
Maintainable JavaScript 2011
Nicholas Zakas
 
PDF
Mobile Open Day: React Native: Crossplatform fast dive
epamspb
 
Intro to React
Troy Miles
 
Callbacks, promises, generators - asynchronous javascript
Łukasz Kużyński
 
Integrating React.js with PHP projects
Ignacio Martín
 
React.js or why DOM finally makes sense
Eldar Djafarov
 
Avoiding callback hell with promises
TorontoNodeJS
 
Discover React
Massimo Iacolare
 
Avoiding Callback Hell with Async.js
cacois
 
History of jQuery
jeresig
 
React
중운 박
 
Mobile Day - React Native
Software Guru
 
JavaScript - From Birth To Closure
Robert Nyman
 
$q and Promises in AngularJS
a_sharif
 
Going fullstack React(ive) - Paulo Lopes - Codemotion Amsterdam 2017
Codemotion
 
Difference between java script and jquery
Umar Ali
 
Containers & Dependency in Ember.js
Matthew Beale
 
The Promised Land (in Angular)
Domenic Denicola
 
Workshop 12: AngularJS Parte I
Visual Engineering
 
Maintainable JavaScript 2011
Nicholas Zakas
 
Mobile Open Day: React Native: Crossplatform fast dive
epamspb
 
Ad

Viewers also liked (7)

PDF
WebSockets, Unity3D, and Clojure
Josh Glover
 
PDF
Unity and WebSockets
Josh Glover
 
PDF
The Case for React.js and ClojureScript
Murilo Pereira
 
PDF
ClojureScript interfaces to React
Michiel Borkent
 
PDF
The algebra of library design
Leonardo Borges
 
PDF
Unity WebSocket
光晶 上原
 
PDF
Clojure の各種React系ラッパーライブラリのサーバーサイドレンダリングの現状について
Kazuhiro Hara
 
WebSockets, Unity3D, and Clojure
Josh Glover
 
Unity and WebSockets
Josh Glover
 
The Case for React.js and ClojureScript
Murilo Pereira
 
ClojureScript interfaces to React
Michiel Borkent
 
The algebra of library design
Leonardo Borges
 
Unity WebSocket
光晶 上原
 
Clojure の各種React系ラッパーライブラリのサーバーサイドレンダリングの現状について
Kazuhiro Hara
 
Ad

Similar to High Performance web apps in Om, React and ClojureScript (20)

PPTX
ReactJS Code Impact
Raymond McDermott
 
PDF
Welcome to React & Flux !
Ritesh Kumar
 
PDF
Introduction to Functional Reactive Web with Clojurescript
John Stevenson
 
PDF
The virtual DOM and how react uses it internally
Clóvis Neto
 
PDF
Workshop 19: ReactJS Introduction
Visual Engineering
 
PPTX
React js - The Core Concepts
Divyang Bhambhani
 
PDF
React js
Rajesh Kolla
 
PDF
Reactjs: Rethinking UI Devel
Stefano Ceschi Berrini
 
PDF
React for Dummies
Mitch Chen
 
PPTX
React JS; all concepts. Contains React Features, JSX, functional & Class comp...
Karmanjay Verma
 
PPTX
Introduction to React JS.pptx
SHAIKIRFAN715544
 
PDF
Functional Web Development
FITC
 
PDF
React & Flux Workshop
Christian Lilley
 
PPTX
Introduction to ReactJS UI Web Dev .pptx
SHAIKIRFAN715544
 
PDF
React && React Native workshop
Stacy Goh
 
PDF
Intro to react_v2
Feather Knee
 
PPTX
ReactJS
Ram Murat Sharma
 
PDF
Ryan Christiani I Heard React Was Good
FITC
 
PPTX
React - An Introduction
Tyler Johnston
 
PDF
React.js - and how it changed our thinking about UI
Marcin Grzywaczewski
 
ReactJS Code Impact
Raymond McDermott
 
Welcome to React & Flux !
Ritesh Kumar
 
Introduction to Functional Reactive Web with Clojurescript
John Stevenson
 
The virtual DOM and how react uses it internally
Clóvis Neto
 
Workshop 19: ReactJS Introduction
Visual Engineering
 
React js - The Core Concepts
Divyang Bhambhani
 
React js
Rajesh Kolla
 
Reactjs: Rethinking UI Devel
Stefano Ceschi Berrini
 
React for Dummies
Mitch Chen
 
React JS; all concepts. Contains React Features, JSX, functional & Class comp...
Karmanjay Verma
 
Introduction to React JS.pptx
SHAIKIRFAN715544
 
Functional Web Development
FITC
 
React & Flux Workshop
Christian Lilley
 
Introduction to ReactJS UI Web Dev .pptx
SHAIKIRFAN715544
 
React && React Native workshop
Stacy Goh
 
Intro to react_v2
Feather Knee
 
Ryan Christiani I Heard React Was Good
FITC
 
React - An Introduction
Tyler Johnston
 
React.js - and how it changed our thinking about UI
Marcin Grzywaczewski
 

More from Leonardo Borges (20)

PDF
Realtime collaboration with Clojure - EuroClojure - Barcelona, 2015
Leonardo Borges
 
PDF
Parametricity - #cljsyd - May, 2015
Leonardo Borges
 
PDF
From Java to Parellel Clojure - Clojure South 2019
Leonardo Borges
 
PDF
Futures e abstração - QCon São Paulo 2015
Leonardo Borges
 
PDF
Functional Reactive Programming / Compositional Event Systems
Leonardo Borges
 
PDF
Programação functional reativa: lidando com código assíncrono
Leonardo Borges
 
PDF
Monads in Clojure
Leonardo Borges
 
PDF
Clojure Macros Workshop: LambdaJam 2013 / CUFP 2013
Leonardo Borges
 
PDF
Intro to Clojure's core.async
Leonardo Borges
 
PDF
Functional Reactive Programming in Clojurescript
Leonardo Borges
 
PDF
Clojure/West 2013 in 30 mins
Leonardo Borges
 
PDF
Clojure Reducers / clj-syd Aug 2012
Leonardo Borges
 
PDF
The many facets of code reuse in JavaScript
Leonardo Borges
 
PDF
Continuation Passing Style and Macros in Clojure - Jan 2012
Leonardo Borges
 
PDF
Heroku addons development - Nov 2011
Leonardo Borges
 
PDF
Clouds against the Floods (RubyConfBR2011)
Leonardo Borges
 
KEY
Clouds Against the Floods
Leonardo Borges
 
KEY
Arel in Rails 3
Leonardo Borges
 
PDF
Testing with Spring
Leonardo Borges
 
PDF
JRuby in The Enterprise
Leonardo Borges
 
Realtime collaboration with Clojure - EuroClojure - Barcelona, 2015
Leonardo Borges
 
Parametricity - #cljsyd - May, 2015
Leonardo Borges
 
From Java to Parellel Clojure - Clojure South 2019
Leonardo Borges
 
Futures e abstração - QCon São Paulo 2015
Leonardo Borges
 
Functional Reactive Programming / Compositional Event Systems
Leonardo Borges
 
Programação functional reativa: lidando com código assíncrono
Leonardo Borges
 
Monads in Clojure
Leonardo Borges
 
Clojure Macros Workshop: LambdaJam 2013 / CUFP 2013
Leonardo Borges
 
Intro to Clojure's core.async
Leonardo Borges
 
Functional Reactive Programming in Clojurescript
Leonardo Borges
 
Clojure/West 2013 in 30 mins
Leonardo Borges
 
Clojure Reducers / clj-syd Aug 2012
Leonardo Borges
 
The many facets of code reuse in JavaScript
Leonardo Borges
 
Continuation Passing Style and Macros in Clojure - Jan 2012
Leonardo Borges
 
Heroku addons development - Nov 2011
Leonardo Borges
 
Clouds against the Floods (RubyConfBR2011)
Leonardo Borges
 
Clouds Against the Floods
Leonardo Borges
 
Arel in Rails 3
Leonardo Borges
 
Testing with Spring
Leonardo Borges
 
JRuby in The Enterprise
Leonardo Borges
 

Recently uploaded (20)

PDF
Unlocking the Future- AI Agents Meet Oracle Database 23ai - AIOUG Yatra 2025.pdf
Sandesh Rao
 
PDF
Tea4chat - another LLM Project by Kerem Atam
a0m0rajab1
 
PDF
Oracle AI Vector Search- Getting Started and what's new in 2025- AIOUG Yatra ...
Sandesh Rao
 
PDF
Presentation about Hardware and Software in Computer
snehamodhawadiya
 
PPTX
OA presentation.pptx OA presentation.pptx
pateldhruv002338
 
PDF
Advances in Ultra High Voltage (UHV) Transmission and Distribution Systems.pdf
Nabajyoti Banik
 
PPTX
Comunidade Salesforce São Paulo - Desmistificando o Omnistudio (Vlocity)
Francisco Vieira Júnior
 
PDF
SparkLabs Primer on Artificial Intelligence 2025
SparkLabs Group
 
PDF
Structs to JSON: How Go Powers REST APIs
Emily Achieng
 
PDF
Using Anchore and DefectDojo to Stand Up Your DevSecOps Function
Anchore
 
PDF
This slide provides an overview Technology
mineshkharadi333
 
PDF
Trying to figure out MCP by actually building an app from scratch with open s...
Julien SIMON
 
PDF
Google I/O Extended 2025 Baku - all ppts
HusseinMalikMammadli
 
PDF
REPORT: Heating appliances market in Poland 2024
SPIUG
 
PDF
Accelerating Oracle Database 23ai Troubleshooting with Oracle AHF Fleet Insig...
Sandesh Rao
 
PDF
Software Development Methodologies in 2025
KodekX
 
PDF
How Open Source Changed My Career by abdelrahman ismail
a0m0rajab1
 
PPTX
New ThousandEyes Product Innovations: Cisco Live June 2025
ThousandEyes
 
PPTX
Coupa-Overview _Assumptions presentation
annapureddyn
 
PDF
The Evolution of KM Roles (Presented at Knowledge Summit Dublin 2025)
Enterprise Knowledge
 
Unlocking the Future- AI Agents Meet Oracle Database 23ai - AIOUG Yatra 2025.pdf
Sandesh Rao
 
Tea4chat - another LLM Project by Kerem Atam
a0m0rajab1
 
Oracle AI Vector Search- Getting Started and what's new in 2025- AIOUG Yatra ...
Sandesh Rao
 
Presentation about Hardware and Software in Computer
snehamodhawadiya
 
OA presentation.pptx OA presentation.pptx
pateldhruv002338
 
Advances in Ultra High Voltage (UHV) Transmission and Distribution Systems.pdf
Nabajyoti Banik
 
Comunidade Salesforce São Paulo - Desmistificando o Omnistudio (Vlocity)
Francisco Vieira Júnior
 
SparkLabs Primer on Artificial Intelligence 2025
SparkLabs Group
 
Structs to JSON: How Go Powers REST APIs
Emily Achieng
 
Using Anchore and DefectDojo to Stand Up Your DevSecOps Function
Anchore
 
This slide provides an overview Technology
mineshkharadi333
 
Trying to figure out MCP by actually building an app from scratch with open s...
Julien SIMON
 
Google I/O Extended 2025 Baku - all ppts
HusseinMalikMammadli
 
REPORT: Heating appliances market in Poland 2024
SPIUG
 
Accelerating Oracle Database 23ai Troubleshooting with Oracle AHF Fleet Insig...
Sandesh Rao
 
Software Development Methodologies in 2025
KodekX
 
How Open Source Changed My Career by abdelrahman ismail
a0m0rajab1
 
New ThousandEyes Product Innovations: Cisco Live June 2025
ThousandEyes
 
Coupa-Overview _Assumptions presentation
annapureddyn
 
The Evolution of KM Roles (Presented at Knowledge Summit Dublin 2025)
Enterprise Knowledge
 

High Performance web apps in Om, React and ClojureScript

  • 1. High Performance Web UI's with Om and React LambdaJam - Brisbane, 2014 Leonardo Borges @leonardo_borges www.leonardoborges.com www.thoughtworks.com
  • 2. About ‣ ThoughtWorker ‣ Functional Programming & Clojure advocate ‣ Founder of the Sydney Clojure User Group ‣ Currently writing “Clojure Reactive Programming”
  • 4. And that makes us happy
  • 5. However if you do client-side web development, you’re out of luck
  • 8. Today we’ll see one of them: Clojurescript
  • 9. What we’ll see ‣ An Overview of React and how it enables fast rendering ‣ Meet Om, a ClojureScript interface to React ‣ Boosting React’s rendering performance with immutable data structures ‣ A simple demo featuring “data binding” and undo functionality
  • 10. React ‣ Created by Facebook for building user interfaces ‣ The V in MVC ‣ Self-contained components ‣ Doesn’t make assumptions about your stack - can be used with anything
  • 11. Self-contained components ‣ React combines display logic and DOM generation ‣ Components are themselves loosely coupled ‣ The whole app is re-rendered on every update ‣ Virtual DOM ‣ Efficient diff algorithm
  • 12. Efficient diff algorithm ‣ Creates a virtual version of the DOM ‣ As the application state changes new DOM trees are generated ‣ React diffs the trees and computes the minimal set of changes ‣ Finally it applies the changes to the real DOM
  • 13. A simple React component var HelloMessage = React.createClass({! displayName: 'HelloMessage',! render: function() {! return React.DOM.div(null, "Hello ", this.props.name);! }! });! ! React.renderComponent(! HelloMessage( {name:"John"} ), mountNode);
  • 15. A simple React component (using the JSX pre-processor) var HelloMessage = React.createClass({! render: function() {! return <div>Hello {this.props.name}</div>;! }! });! ! React.renderComponent(! <HelloMessage name="John" />, mountNode);
  • 16. React components are functions from application state to a DOM tree
  • 17. Now let’s take a leap and look at the same component, written in Om
  • 18. A simple Om component (def app-state (atom {:name "Leo"}))! ! (defn hello-message [app owner]! (reify om/IRender! (render [_]! (dom/div nil! (str "Hello " (:name app))))))! ! ! (om/root hello-message app-state! {:target (. js/document (getElementById "hello"))})!
  • 19. Om/React’s component lifecycle IWillMountIInitState IShouldUpdate IRender IRenderState
  • 20. IShouldUpdate ‣ Called on app state changes but before rendering ‣ This is where React uses its fast diff algorithm ‣ Om components implement the fastest algorithm possible: a simple reference equality check ‣ Generally, you won’t have to implement this
  • 21. IInitState & IRenderState ‣ Initialise component local state using IInitState ‣ Use IRenderState to work with it and render the component
  • 22. IInitState & IRenderState (defn counter [app owner]! (reify! om/IInitState! (init-state [_]! {:clicks 0})! om/IRenderState! (render-state [_ state]! (dom/div nil! (str "Clicks " (:clicks state))! (dom/button #js {:onClick! #(om/set-state! owner :clicks (inc (:clicks state)))}! "Click me!")))))! ! (om/root counter (atom {})! {:target (. js/document (getElementById "app"))})!
  • 23. IRender ‣ Same as IRenderState… ‣ …except it doesn’t depend on the component local state to render
  • 24. IRender (def app-state (atom {:name "Leo"}))! ! (defn hello-message [app owner]! (reify om/IRender! (render [_]! (dom/div nil! (str "Hello " (:name app))))))! ! ! (om/root hello-message app-state! {:target (. js/document (getElementById "hello"))})!
  • 27. A reusable editable component (defn editable [text owner]! (reify! om/IInitState! (init-state [_]! {:editing false})! om/IRenderState! (render-state [_ {:keys [editing]}]! (dom/li nil! (dom/span #js {:style (display (not editing))} (om/value text))! (dom/input! #js {:style (display editing)! :value (om/value text)! :onChange #(handle-change % text owner)! :onKeyPress #(when (== (.-keyCode %) 13)! (commit-change text owner))! :onBlur (fn [e] (commit-change text owner))})! (dom/button! #js {:style (display (not editing))! :onClick #(om/set-state! owner :editing true)}! "Edit")))))! From https://github.com/swannodette/om/wiki/Basic-Tutorial
  • 28. A reusable editable component (defn editable [text owner]! (reify! om/IInitState! (init-state [_]! {:editing false})! om/IRenderState! (render-state [_ {:keys [editing]}]! (dom/li nil! (dom/span #js {:style (display (not editing))} (om/value text))! (dom/input! #js {:style (display editing)! :value (om/value text)! :onChange #(handle-change % text owner)! :onKeyPress #(when (== (.-keyCode %) 13)! (commit-change text owner))! :onBlur (fn [e] (commit-change text owner))})! (dom/button! #js {:style (display (not editing))! :onClick #(om/set-state! owner :editing true)}! "Edit")))))! From https://github.com/swannodette/om/wiki/Basic-Tutorial
  • 29. A reusable editable component (defn editable [text owner]! (reify! om/IInitState! (init-state [_]! {:editing false})! om/IRenderState! (render-state [_ {:keys [editing]}]! (dom/li nil! (dom/span #js {:style (display (not editing))} (om/value text))! (dom/input! #js {:style (display editing)! :value (om/value text)! :onChange #(handle-change % text owner)! :onKeyPress #(when (== (.-keyCode %) 13)! (commit-change text owner))! :onBlur (fn [e] (commit-change text owner))})! (dom/button! #js {:style (display (not editing))! :onClick #(om/set-state! owner :editing true)}! "Edit")))))! From https://github.com/swannodette/om/wiki/Basic-Tutorial
  • 30. The speakers view (defn speakers-view [app owner]! (reify! om/IRender! (render [_]! (dom/div nil! (dom/div #js {:id "speakers"! :style #js {:float "left"}}! (dom/h2 nil "Speakers")! (dom/button #js {:onClick undo} "Undo")! (dom/button #js {:onClick reset-app-state} "Reset")! (apply dom/ul nil! (om/build-all speaker-view (speakers app)! {:shared {:app-state app}})))! (om/build speaker-details-view app))))) This is how you build components
  • 31. The Sessions view Same deal as before (defn sessions-view [app owner]! (reify! om/IRender! (render [_]! (dom/div #js {:id "sessions"}! (dom/h2 nil "Sessions")! (apply dom/ul nil! (map #(om/build editable %) (vals (:sessions app))))))))!
  • 32. Apps can have multiple roots (om/root speakers-view app-state! {:target (. js/document (getElementById "speakers"))})! ! (om/root sessions-view app-state! {:target (. js/document (getElementById "sessions"))})! You can have multiple “mini-apps” inside your main app Makes it easy to try Om in a specific section/feature
  • 33. What about “undo” and “reset”?
  • 34. Implementing undo (def app-state (atom speaker-data))! (def app-history (atom [@app-state]))! ! (add-watch app-state :history! (fn [_ _ _ n]! (when-not (= (last @app-history) n)! (swap! app-history conj n))! (let [c (count @app-history)]! (prn c " Saved items in app history"))))! ! (defn undo []! (when (> (count @app-history) 1)! (swap! app-history pop)! (reset! app-state (last @app-history))))!
  • 35. Implementing reset (defn reset-app-state []! (reset! app-state (first @app-history))! (reset! app-history [@app-state]))!
  • 36. Om/React components are functions from state to DOM trees
  • 37. With immutable data structures we can access every version of the application state
  • 38. So we simply update the application state, causing the components to get re-rendered
  • 39. A bit of live coding
  • 40. Summary ‣ With Om, you’re not using a crippled template language, you can leverage all of Clojurescript (including other DOM libraries) ‣ Rendering and display logic are inevitably coupled. Om/React acknowledges that a bundles them in components ‣ The whole app is re-rendered on every state change, making it easier to reason about ‣ This is efficient thanks to immutable data structures
  • 41. Summary ‣ Clojurescript also provides a better development experience with a powerful browser REPL much like what you’d get with Clojure on the JVM ‣ Source maps are here today ‣ Bottom line is that Clojurescript is a serious contender
  • 42. References ‣ Code: https://github.com/leonardoborges/lambdajam-2014-om-talk ‣ React documentation: http://facebook.github.io/react/ ‣ Om documentation: https://github.com/swannodette/om/wiki/ Documentation#build ‣ Basic Tutorial: https://github.com/swannodette/om/wiki/Basic-Tutorial