Top Banner
Reactive programming in ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016
111

Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Oct 09, 2020

Download

Documents

dariahiddleston
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Reactive programming in ClojureScript using React.js wrappers

Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016

Page 2: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

State of the web development

More and more complex apps

Solving elaborate problems

Myriad of web browsers and devices

Performance and resources

Page 3: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Plain vanilla JavaScript

Page 4: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

JQuery

Page 5: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

MVC

Page 6: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

React.js

Page 7: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

What does it mean reactive?

Erik Meijer - What does it mean to be Reactive?

Lots of definitions

Difficult to agree

Page 8: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Components reacting to events and changing state

Page 9: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Apples

Oranges

Grapes

Page 10: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Add pineapple

But how exactly?

Page 11: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Solution #1

Insert a new list item

Find the right place

Page 12: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Solution #2

Throw out the entire list and rebuild it

Rendering large scale amounts of DOM is slow

Page 13: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Most JS frameworks help to mitigate problem #1

Make DOM easier to navigate

Tie element to a controller keeping it up to date

Page 14: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

React solves problem #2

Page 15: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Virtual DOM (two copies)

Original

Updated

Page 16: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Compare new virtual DOM with previous

Render only bits that have changed

Page 17: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Pretending to re-render entire page is fast

Easier to reason about

Page 18: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

V in MVC

Interfaces with changing data

Can combine with frameworks e.g. AngularJS

Page 19: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Flux architecture

Once-directional data flow

Action → Dispatcher → Store → View

Page 20: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

JavaScript sucks

Page 21: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

this

Verbose syntax

Confusing, inconsistent automatic operator conversions

NaN

Global variables by default

etc.

Page 22: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

We need JavaScript

JS is (almost) everywhere

Runtime is improving

Web Sockets

WebRTC

Canvas

Push notifications

Page 23: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Build “better” language on top of JS

Page 24: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

1 + 2 // simple, clear

(+ 1 2) ; OMG! So confusing

Clearly programmers aren't that smart as some think

Page 25: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

ClojureScript

Modern LISP

Immutable data structures

State vs Identity

REPL

Transducers

core.async

And much much more

Page 26: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

ClojureScript + React.js

Page 27: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Pure React.js is not idiomatic in ClojureScript

Leverage immutable data structures

Page 28: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

ClojureScript React.js wrappers on steroids

Page 29: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Rum

Not a framework but a library

Page 30: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Om, Reagent, Quiescent have built-in component behaviour model

Page 31: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Rum

Two-level API

Page 32: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Rum

Define your component and render it

Page 33: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

(rum/defc name doc-string? [params*] render-body+)

Page 34: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

(rum/defc h1 [text] [:h1 text])

(rum/mount (h1 "important") js/document.body)

Page 35: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Simple component not reactive

Agnostic of data storage and behaviour model

Page 36: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Use mixins to control component's behaviour

Page 37: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Pre-built component mixins

Mimic behaviour of other wrappers

Page 38: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

(rum/defc name doc-string? [< mixins+]? [params*] render-body+)

Page 39: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Static mixin

Checks if args have changed

Avoids re-rendering if they are the same

Page 40: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

(rum/defc h1 < rum/static [text][:h1 text])

Page 41: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

(rum/mount (h1 "important text") body)

(rum/mount (h1 "important text") body) ;; render won’t be called

(rum/mount (h1 "important") body) ;; this will cause re-rendering

Page 42: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Local Mixin

Rum local

Per-component local state

Page 43: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State
Page 44: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State
Page 45: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State
Page 46: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

(rum/defcs make-service < (rum/local "") [state service](let [local (:rum/local state)]

[:p {:class @local

:on-click (fn [_] (swap! local toggle-class service))}

(:name service)

[:b (str " £" (:price service))]]))

Page 47: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

(defn toggle-class [current-class service] (let [price (:price service)]

(if (= current-class "active")

(do (swap! order-form-total - price)

"")

(do (swap! order-form-total + price)

"active"))))

Page 48: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Reactive mixin

Creates “reactive” component

Tracks references to data

Auto-updates when value stored changes

Reactive mixin is like Reagent wrapper

Page 49: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State
Page 50: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

(def order-form-total (atom 0))

(rum/defc total-sum < rum/reactive [] [:p {:id "total"} (str "Total: £" (rum/react order-form-total))])

Page 51: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

(defn toggle-class [current-class service] (let [price (:price service)]

(if (= current-class "active")

(do (swap! order-form-total - price)

"")

(do (swap! order-form-total + price)

"active"))))

Page 52: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Cursored mixin

Interface to sub-trees inside an atom

Like an Om wrapper

Page 53: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

(def state (atom {:app { :settings {:header {:colour "#cc3333" }}}}))

Page 54: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

(rum/defc label < rum/cursored [colour text] [:label {:style {:colour @colour}} text])

Page 55: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

(rum/defc body < rum/cursored [state] [:div

(label (rum/cursor state [:app :settings :headers :colour]) "First label" )])

Page 56: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

(swap! state-cursor assoc-in [:app :settings :header :colour] "#cc56bb")

Page 57: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

One global state

Atomic swaps

Always consistent

Easy to implement undo – reset to previous state

Serialize app state and send it over the wire

Page 58: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Custom mixin

Use React.js life-cycle functions

Will mount

Did mount

Should update

Will unmount

Page 59: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Scrolling mixin

Page 60: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

(defn scroll-view [height] {:did-mount (fn [state]

(if-not (::scrolled state)

(do

(set-scroll-top! height)

(assoc state ::scrolled true))

state))

:transfer-state (fn [old new]

(assoc new ::scrolled (::scrolled old)

::with-scroll-view true))})

Page 61: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Build new mixins easily

Page 62: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Mix and match different mixins

Page 63: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

The curious case of Om

Page 64: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

The good, the bad and the future

Page 65: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Root UI is given root cursor

Passes sub-trees of cursors to its sub-components

Page 66: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

{:list {:title "My list:" :colour :brown My list:

:items

{:item_1 {:text "text1" :colour :blue} - text1

:item_2 {:text "text2" :colour :green} - text2

:item_3 {:text "text3" :colour :red}}}} - text3

Page 67: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Case #1

UI cross-cutting concerns?

Page 68: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Dashboard with a list that can be expanded, shrank

Page 69: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Save the list presentation options to general settings?

Page 70: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Cursor-oriented architecture requires you to structure app state as a tree (matching UI)

Page 71: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Quite often your data are not a tree

Page 72: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Changing item's text is easy

Page 73: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Case #2

Deleting an item should be easy too, right?

Page 74: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Does delete button/option belong to an item or a list?

Page 75: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Deleting an item requires list manipulation

Page 76: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Rum is flexible use it if you can

Page 77: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Enter Om.next

New version of Om

Page 78: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Actually a reboot

Page 79: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Experience of the last few years

Inspired by:

Facebook's Relay

Netflix's Falcor

Cognitect's Datomic

Page 80: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Display date of past purchases of certain item

Page 81: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

{:current-user

{:purchases

[{:id 146

:product-name "organic rice"

:date #inst "2015-12-17T17:13:59.167-00:00"

:previous {:id 140

:product-name "organic rice"

:date #inst "2015-12-14T17:05:58.144-00:00"

:previous {:id 136

:product-name "organic rice"

:date #inst "2015-12-10T17:05:13.512-00:00"

:previous ; and so on... }}}

{:id 145

:product-name "soy milk"

:date #inst "2015-12-17T17:09:25.961-00:00"

:previous {:id 141

:product-name "soy milk"

:date #inst "2015-12-15T17:05:36.797-00:00"

:previous {:id 128

:product-name "soy milk"

:date #inst "2015-12-07T17:04:51.124-00:00"

:previous ; and so on... }}}]}}

Page 82: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

{:current-user {:recent-purchases [[:purchase-id 146]

[:purchase-id 145]]}

:purchased-items {146 {:id 146

:product-name "organic rice"

:date #inst "2015-12-17T17:13:59.167-00:00"

:previous [:purchase-id 144]}

145 {:id 145

:product-name "soy milk"

:date #inst "2015-12-17T17:09:25.961-00:00"

:previous [:purchase-id 143]}

144 {:id 144

:product-name "organic rice"

:date #inst "2015-12-17T17:05:58.144-00:00"

:previous [:purchase-id 141]}

143 {:id 143

:product-name "soy milk"

:date #inst "2015-12-17T17:05:36.797-00:00"

:previous [:purchase-id 138]}

;; and so on... }}

Page 83: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

In Om.next components define a query to data they need

Page 84: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Cursor navigates a tree, query can navigate a graph

Page 85: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

[{:current-user [{:recent-purchases [{:previous [:date]}]}]}]

Page 86: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

{:current-user {:recent-purchases

[{:previous {:date #inst "2015-12-17T17:05:58.144-00:00"}}

{:previous {:date #inst "2015-12-17T17:05:36.797-00:00"}}]}}

Page 87: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

{:current-user {:recent-purchases [[:purchase-id 146]

[:purchase-id 145]]}

:purchased-items {146 {:id 146

:product-name "organic rice"

:date #inst "2015-12-17T17:13:59.167-00:00"

:previous [:purchase-id 144]}

145 {:id 145

:product-name "soy milk"

:date #inst "2015-12-17T17:09:25.961-00:00"

:previous [:purchase-id 143]}

144 {:id 144

:product-name "organic rice"

:date #inst "2015-12-17T17:05:58.144-00:00"

:previous [:purchase-id 141]}

143 {:id 143

:product-name "soy milk"

:date #inst "2015-12-17T17:05:36.797-00:00"

:previous [:purchase-id 138]}

;; and so on... }}

Page 88: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

{:current-user {:recent-purchases

[{:previous {:date #inst "2015-12-17T17:05:58.144-00:00"}}

{:previous {:date #inst "2015-12-17T17:05:36.797-00:00"}}]}}

Page 89: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Om.next normalizes data* you have into one you expect

* with a little help from you

Page 90: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

{:list/one [{:product-name "soy milk" :price 10} {:product-name "eggs" :price 22}

{:product-name "juice" :price 26}]

:list/two [{:product-name "eggs" :price 22 :discount 7}

{:product-name "apples" :price 8}

{:product-name "cereals" :price 37 :discount 15}]}

Page 91: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

(defui Product static om/Ident

(ident [this {:keys [product-name]}]

[:product/by-name product-name])

static om/IQuery

(query [this]

'[:name :price :discount])

Object

(render [this]

;; ... elided ...))

Page 92: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

(d{:list/one [[:product/by-name "soy milk"]

[:product/by-name "eggs"]

[:product/by-name "juice"]],

:list/two

[[:product/by-name "eggs"]

[:product/by-name "apples"]

[:product/by-name "cereals"]],

:product/by-name

{"soy milk" {:name "soy milk", :price 10},

"eggs" {:name "eggs", :price 22, :discount 7},

"juice" {:name "juice", :price 26}, "apples" {:name "apples", :price 8},

"cereals" {:name "cereals", :price 37, :discount 15}}

Page 93: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Store data the way you want and let Om.next convert data to match your UI

Page 94: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Om.next

Currently in alpha stage

Production ready in a couple of months

Page 95: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Datascript

Because good things come in pairs

Nikita Prokopov creator of Rum and Datascript

Page 96: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Immutable in-memory database

Datalog as a query engine

Page 97: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Central, uniform approach to manage all application state

Page 98: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Schemaless DB < Datascript < Relational schema

Data already normalized

Page 99: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

{:db/id #db/id[:db.part/db]

:db/ident :product/name

:db/valueType :db.type/string

:db/cardinality :db.cardinality/one

:db/unique :db.unique/identity

:db/doc "Product's name"}

{:db/id #db/id[:db.part/db]

:db/ident :product/price

:db/valueType :db.type/number

:db/cardinality :db.cardinality/one

:db/doc "Product's price"}

Page 100: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Datalog query

[:find ?name ?price ?discount :where [?p :product/name ?name] [?p :product/price ?price] [?p :product/discount ?discount]]

Page 101: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

(defui Product static om/Ident

(ident [this {:keys [product-name]}]

[:product/by-name product-name])

static om/IQuery

(query [this]

'[:name :price :discount])

Object

(render [this]

;; ... elided ...))

Page 102: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Find specific item

[:find ?name ?price ?discount :in $ ?name :where [?p :product/name ?name] [?p :product/price ?price] [?p :product/discount ?discount]]

Page 103: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

(rum/defc product-item [db name]

(let [item (d/q '[:find ?name ?price ?discount :in $ ?name :where [?p :product/name ?name] [?p :product/price ?price] [?p :product/discount ?discount]] db name)]

(when item

[:p name "$" (:product/price item) "discount $" (:product/discount item)])))

Page 104: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Write components that depend on return values of queries

Page 105: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Database as a value

Page 106: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Summary

React.js is interesting – give it a go

ClojureScript is interesting too

React.js + ClojureScript = awesome

Interesting wrappers for React.js in ClojureScript with some cool technologies

Page 107: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Questions???

Page 108: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Tweet me: @ryujinkony

Konrad Szydlogithub

retailic.com

Page 109: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Retailic

Retailic helps retail to draw business conclusions from consumer behaviour and develop corresponding software solutions.

Page 110: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Resources

https://www.youtube.com/watch?v=sTSQlYX5DU0 Eric Meijer

https://medium.com/@carloM/reactive-programming-with-kefir-js-and-react-a0e8bb3af636#.td9mdlfzr Reactive programming with react.js

http://blog.ractivejs.org/posts/whats-the-difference-between-react-and-ractive/ React.js vs Ractive

http://www.funnyant.com/reactjs-what-is-it/

Page 111: Reactive programming in ClojureScript using React.js wrappers · 2020. 8. 18. · ClojureScript using React.js wrappers Konrad Szydlo @ Lambda Days, Krakow, 19 February 2016. State

Resources

https://www.destroyallsoftware.com/talks/wat

https://github.com/active-group/reacl

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

https://github.com/tonsky/rum

https://github.com/tonsky/datascript

https://github.com/omcljs/om/wiki