<commit_before><!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

    <title>Calmm training</title>

    <link rel="stylesheet" href="css/reveal.css">
    <link rel="stylesheet" href="css/theme/black.css">

    <!-- Theme used for syntax highlighting of code -->
    <link rel="stylesheet" href="lib/css/zenburn.css">

    <!-- Printing and PDF exports -->
    <script>
      var link = document.createElement( 'link' );
      link.rel = 'stylesheet';
      link.type = 'text/css';
      link.href = window.location.search.match( /print-pdf/gi ) ? 'css/print/pdf.css' : 'css/print/paper.css';
      document.getElementsByTagName( 'head' )[0].appendChild( link );
    </script>
  </head>
  <body>
    <div class="reveal">
      <div class="slides">
        <section>
          <section>
            <h1>Calmm Training</h1>
            <p>Join #calmm on Slack</p>
            <small><NAME></small>
          </section>
          <section>
            <h2>Agenda</h2>
            <ul>
              <li class="fragment">Introduction to Calmm</li>
              <li class="fragment">Hands-on excercises</li>
              <li class="fragment">How to start using Calmm today</li>
              <li class="fragment">Benefits of Calmm</li>
              <li class="fragment">Painpoints with Calmm</li>
            </ul>
          </section>
        </section>
        <section>
          <h2>What is Calmm?</h2>
          <ul>
            <li class="fragment">An architecture and a collection of libraries</li>
            <li class="fragment">Declarative and boilerplate-free way to write reactive UIs</li>
            <li class="fragment">Some of the libraries are React specific but not all</li>
            <li class="fragment">Observables are used for dependent computations, Bacon or Kefir</li>
          </ul>
        </section>
        <section>
          <h2>How is it different from traditional React?</h2>
        </section>
        <section>
          <section>
            <h3>Observables are embedded directly in the VDOM</h3>
          </section>
          <section>
            <pre><code data-trim class="jsx">
  import * as React from 'baret' // or karet for Kefir

  const MyComponent = () => {
    const time = Bacon.once()
      .merge(Bacon.interval(1000))
      .map(() => new Date().toString())
      .toProperty()

    return &lt;div&gt;The time is &lt;strong&gt;{time}&lt;/strong&gt;&lt;/div&gt;
  }
            </code></pre>
            <p class="fragment">karet and baret hooks into the createElement API of React, which is the reason you need to import React from karet or baret library.</p>
          </section>
          <section>
            <h2>Embedding observables directly into VDOM has a lot of benefits</h2>
          </section>
          <section>
            <small>
              <h2>Completely boilerplate-free</h2>
              <ul>
                <li class="fragment">State is stored in modifiable and observable atoms (more about this in a minute)</li>
                <li class="fragment">No glue code needed to transform external state into props or internal React component state</li>
                <li class="fragment">
                  No need for
                  <pre><code data-trim class="js">
Bacon.combineTemplate({
  todos: todosProperty,
  counter: counterProperty
})
  .takeUntil(componentUnmountStream)
  .onValue(state => this.setState(state))
                  </code></pre>
                </li>
                <li class="fragment">
                  ... or ...
                  <pre><code data-trim class="js">
const mapStateToProps = (state, ownProps) => ({
  todos: state.todos,
  counter: state.counter
})
const mapDispatchToProps = ...
const WrappedComponent = connect(mapStateToProps, mapDispatchToProps)(TodoComponent)
                  </code></pre>
                </li>
                <li class="fragment">
                  ... etc.
                </li>
              </ul>
            </small>
          </section>
          <section>
            <small>
              <h2>Observable life-cycle is automatic</h2>
              <ul>
                <li class="fragment">Calmm subscribes to your observables when a component is mounted</li>
                <li class="fragment">... and unsubscribes when unmounted</li>
                <li class="fragment">
                  ... but only when the VDOM path is actually being rendered:
                  <pre class="fragment"><code data-trim>
const UselessComponent = ({ observable }) =>
  &lt;div&gt;
    {new Date().getFullYear() >= YEAR_OF_LINUX_DESKTOPS
      ? observable
      : 'The year of the linux desktops is not yet here'}
  &lt;/div&gt;
                  </code></pre>
                  <p class="fragment">observable is only subscribed to if the year of linux desktops has been reached.</p>
                </li>
                <li class="fragment">Enables you to lazily process dependent computations, which is very useful for expensive computations, or computations that may not need to be processed at all.</li>
                <li class="fragment">... and you get this without writing a single line of extra code.</li>
              </ul>
            </small>
          </section>
          <section>
            <small>
              <h2>When an observable changes only the relevant part of the VDOM is updated</h2>
              <pre class="fragment"><code data-trim>
  const MyComponent = ({ observable }) =>
    &lt;div&gt;
      &lt;ComplexComponent /&gt;
      The value of observable is: &lt;strong&gt;{observable}&lt;/strong&gt;
    &lt;/div&gt;
              </code></pre>
              <ul>
                <li class="fragment">When observable changes, only the strong element is re-rendered</li>
                <li class="fragment">Fast incremental VDOM updates</li>
                <li class="fragment">No need for shouldComponentUpdate</li>
                <li class="fragment">Eliminates need for render optimization in vast majority of cases</li>
                <li class="fragment">There are exceptions though</li>
              </ul>
            </small>
          </section>
          <section>
            <small>
              <h3>You can write your components using functional React components</h3>
              <ul>
                <li class="fragment">No need for createClass or React.Component</li>
                <li class="fragment">The function is only called once, on mount</li>
                <li class="fragment">Concise components, with a lot of the React boilerplate removed</li>
              </ul>
            </small>
          </section>
        </section>
        <section>
          <section>
            <h3>Component properties can either be values or observables</h3>
          </section>
          <section>
            <small>
              <h3>Example: working with values and observables</h3>
              <pre><code data-trim class="jsx">
const MultiplyByTwo = ({ number }) => &lt;div>{number * 2}&lt;/div&gt;
              </code></pre>
              <p class="fragment">Does not work with observables.</p>

              <pre class="fragment"><code data-trim class="jsx">
const MultiplyByTwo = ({ number }) => &lt;div&gt;{number.map(it => it * 2)}&lt;/div&gt;
              </code></pre>
              <p class="fragment">Does not work with plain values.</p>

              <pre class="fragment"><code data-trim class="jsx">
import * as U from 'karet.util'
import * as R from 'kefir.ramda'

const MultiplyByTwoA = ({ number }) => &lt;div&gt;{U.mapValue(it => it * 2, number)}&lt;/div&gt;
const MultiplyByTwoB = ({ number }) => &lt;div&gt;{R.multiply(number, 2)}&lt;/div&gt;
              </code></pre>
              <p class="fragment">Works with both!</p>
              <p class="fragment">U.mapValue and R.multiply are <strong>lifted</strong> to work with both plain values and observables.</p>
            </small>
          </section>
          <section>
            <small>
              <h3>Lifted functions</h3>
              <ul>
                <li class="fragment">If you have a function that works with plain values, <strong>lifting</strong> it means that the lifted version can accept plain values and observables as arguments.</li>
                <li class="fragment">When a lifted function is called with only plain values as arguments, the result is computed immediately and is also a plain value.</li>
                <li class="fragment">When any of the arguments is an observable, the result is an observable as well.</li>
                <li class="fragment"><strong>karet.util</strong> (and <strong>baret.util</strong>) contain a lot of useful utility functions, many of which are lifted.</li>
                <li class="fragment">Calmm also has a few wrapper libraries that lift the functions of the wrapped libraries, i.e. <strong>kefir.ramda</strong> and <strong>kefir.partial.lenses</strong>.</li>
                <li class="fragment">
                  It is easy to lift your own functions to work with observables:
                  <pre class="fragment"><code data-trim class="js">
import * as U from 'karet.util'

const includes = U.lift((xs, x) => xs.includes(x))
const obsOfBooleans = includes(obsOfArrays, obsOfValues)
                  </code></pre>
                </li>
              </ul>
            </small>
          </section>
          <section>
            <small>
              <h3>Examples of lifted utility functions in calmm</h3>
              <pre class="fragment"><code data-trim class="jsx">
const PositiveAndLessThan100 = ({ number }) =>
  &lt;div&gt;
    Is {number} positive and less than 100:
    {U.ifElse(
      U.and(R.gte(number, 0), R.lt(number, 100)),
      'yes',
      'no')}
  &lt;/div&gt;
              </code></pre>
              <p class="fragment">Also possible to write</p>
              <pre class="fragment"><code data-trim class="jsx">
const PositiveAndLessThan100 = ({ number }) =&gt; {
  const test = U.lift(number =&gt; number &gt;= 0 && number &lt; 100)
  return (
    &lt;div&gt;
      Is {number} positive and less than 100: {U.ifElse(test(number), 'yes', 'no')}
    &lt;/div&gt;
  )
}
              </code></pre>
              <p class="fragment">or</p>
              <pre class="fragment"><code data-trim class="jsx">
const PositiveAndLessThan100 = ({ number }) =>
  &lt;div&gt;
    Is {number} positive and less than 100:
    {U.mapValue(number =&gt; (number &gt;= 0 && number &lt; 100) ? 'yes' : 'no', number)}
  &lt;/div&gt;
              </code></pre>
              <p class="fragment">If you have complex conditions it is sometimes useful to break down the logic into a separate lifted function for readability.</p>
            </small>
          </section>
          <section>
            <small>
              <h3>Examples of lifted utility functions in calmm</h3>
              <ul>
                <li class="fragment">What you saw in the previous examples were examples of dependent computations.</li>
                <li class="fragment">When the inputs change, so do the outputs. The output can be a plain value, another component, etc.</li>
                <li class="fragment">When the observables change, the dependent computations are re-run, keeping your UI consistent with your application state.</li>
                <li class="fragment">Even complex and asynchronous computations are quite trivial compared to many other tools.</li>
              </ul>
            </small>
          </section>
          <section>
            <small>
              <h3>Example of an asynchronous dependent computation</h3>
              <pre><code data-trim class="jsx">
const Search = ({ text = U.atom('') }) =&gt; {
  const getSearchUrl = text =&gt; `https://my.api/search?text=${encodeURIComponent(text)}`

  const results = U.thru(
    text,
    U.debounce(300),
    U.flatMapLatest(text =&gt; U.thru(
      U.fromPromise(() =&gt; fetch(getSearchUrl(text))),
      U.startWith(undefined)
    )),
    U.startWith([])
  )

  return (
    &lt;div&gt;
      &lt;U.Input value={text} /&gt;
      {U.ifElse(
        R.is(Array, results),
        &lt;ul&gt;
          {U.mapElems((result, i) =&gt; &lt;li key={i}&gt;{result}&lt;/li&gt;, results)}
        &lt;/ul&gt;,
        'Loading'
      )}
    &lt;/div&gt;
  )
}
              </code></pre>
            </small>
          </section>
        </section>
        <section>
          <section>
            <h2>Atoms</h2>
            <ul>
              <li class="fragment">Used to store state</li>
              <li class="fragment">Atoms are observable (properties)</li>
              <li class="fragment">Atoms are modifiable (modify / set)</li>
              <li class="fragment">Stored state is immutable data</li>
              <li class="fragment">Can be decomposed into smaller slices of state using lenses</li>
            </ul>
          </section>
          <section>
            <pre><code data-trim class="jsx">
const Counter = ({ count = Atom(0) }) =>
  &lt;span&gt;
    &lt;button onClick={() =&gt; count.modify(R.add(-1))}&gt;-&lt;/button&gt;
    {count}
    &lt;button onClick={() =&gt; count.modify(R.add(1))}&gt;+&lt;/button&gt;
  &lt;/span&gt;
            </code></pre>
            <small class="fragment">Having the count atom as a parameter makes it easy to use the component with local or global (external) state, ultimately making the component more composeable.</small>
            <pre class="fragment"><code data-trim class="jsx">
&lt;Counter /&gt;
            </code></pre>
            <pre class="fragment"><code data-trim class="jsx">
const count = Atom(10)
&lt;Counter count={count} /&gt;
            </code></pre>
          </section>
          <section>
            <h2>Lenses & lensed atoms</h2>
            <ul>
              <li class="fragment">Lensed atom is a subset of an atom that is decomposed with a lens</li>
              <li class="fragment">Lensed atoms are observable (properties)</li>
              <li class="fragment">Lensed atoms are modifiable (modify / set)</li>
              <li class="fragment">Can be decomposed into even smaller slices using lenses</li>
              <li class="fragment">Easily build a data structure that follows the structure of your UI</li>
            </ul>
          </section>
          <section>
            <small>
              <h3>Example: decompose state to child components</h3>
              <pre><code data-trim class="jsx">
const counters = Atom([0, 0, 0])

&lt;Counter count={counters.view(0)} /&gt;
&lt;Counter count={counters.view(1)} /&gt;
&lt;Counter count={counters.view(2)} /&gt;
              </code></pre>
            </small>
          </section>
          <section>
            <small>
              <h3>Example: filter a list to only show some elements</h3>
              <pre><code data-trim class="jsx">
const todos = Atom([
  { title: 'Wash laundry', finished: false },
  { title: 'Buy groceries', finished: true },
  { title: 'Clean kitchen', finished: false }
])

const TodoList = ({ todos }) =>
  &lt;div&gt;
    &lt;h2&gt;Todo&lt;/h2&gt;
    {U.mapElems(
      (todo, i) =&gt; &lt;TodoItem key={i} todo={todo} /&gt;,
      todos
    )}
  &lt;/div&gt;

const UnfinishedTodos = ({ todos }) => {
  const onlyUnfinishedLens = L.filter(todo => !todo.finished)
  return &lt;TodoList todos={todos.view(onlyUnfinishedLens)} /&gt;
}
              </code></pre>
            </small>
          </section>
          <section>
            <small>
              <h3>Example: change a value in an object</h3>
              <pre><code data-trim class="jsx">
const obj = Atom({
  foo: {
    bar: [1, 2, 3]
  }
})

// focus the 2nd element of the foo.bar array
const slice = obj.view(['foo', 'bar', 1])

slice.set(20)
obj.get() // { foo: { bar: [ 1, 20, 3 ] }}

slice.modify(R.multiply(2))
obj.get() // { foo: { bar: [ 1, 40, 3 ] }}
              </code></pre>
            </small>
          </section>
          <section>
            <small>
              <h3>Example: append a value to a list</h3>
              <pre><code data-trim class="jsx">
const list = Atom({ items: ['x', 'y'] })
list.modify(L.set(['items', L.append], 'z'))
list.get() // { items: ['x', 'y', 'z'] }
              </code></pre>
              <div class="fragment">
                Without the L.append
                <pre><code data-trim class="jsx">
const list = Atom({ items: ['x', 'y'] })
list.modify(L.set(['items'], 'z'))
list.get() // { items: 'z' }
                </code></pre>
              </div>
              <div class="fragment">
                For simple appends Ramda's R.append is usually simpler though
                <pre><code data-trim class="jsx">
const list = Atom(['x', 'y'])
list.modify(R.append('z')) // list.modify(L.set(L.append, 'z'))
list.get() // ['x', 'y', 'z']
                </code></pre>
              </div>
            </small>
          </section>
          <section>
            <small>
              <h3>Example: remove a value from a list</h3>
              <pre><code data-trim class="jsx">
const list = Atom(['x', 'y', 'z'])
list.modify(L.remove(1))
list.get() // ['x', 'z']
              </code></pre>
              <p class="fragment">Lensed atoms can also remove themselves</p>
              <pre class="fragment"><code data-trim class="jsx">
const list = Atom(['x', 'y', 'z'])
const item = list.view(1)
item.remove()
list.get() // ['x', 'z']
              </code></pre>
              <p class="fragment">This is a very useful pattern when you want to have removable UI components where the remove button is in the removable component itself.</p>
            </small>
          </section>
          <section>
            <small>
              <h3>Lenses/optics are very powerful, this is just scratching the surface</h3>
              <ul>
                <li class="fragment">Fetch data from API and transform into format that UI expects.</li>
                <li class="fragment">Make changes via UI, lenses are bidirectional so you can instantly PUT changes back to API. Just define the format of your data via lenses once.</li>
                <li class="fragment">Define default & required values.</li>
                <li class="fragment">Not just lenses. Traversals and isomorphisms.</li>
              </ul>
            </small>
          </section>
        </section>
        <section>
          <small>
            <h3>Calmm libraries we will be using today</h3>
            <ul>
              <li class="fragment"><strong>karet</strong> - embedding Kefir observables in React VDOM</li>
              <li class="fragment"><strong>kefir.atom</strong> - managing the state</li>
              <li class="fragment"><strong>karet.util</strong> - utilities for karet; today we are mainly interested in U.mapElems for easily iterating over an array of values in atom</li>
              <li class="fragment"><strong>partial.lenses</strong> - decomposing atoms with lenses</li>
            </ul>
          </small>
        </section>
        <section>
          <section>
            <h3>Excercise: a simple contact book React application</h3>
            <p class="fragment">Open <a href="https://codesandbox.io/s/4wyz1lo5y0" target="_blank">https://codesandbox.io/s/4wyz1lo5y0</a> in your browser and fork it.</p>
          </section>
          <section>
            <h3>Task 1</h3>
            <p>Re-factor the Contact component to a calmm-style component.</p>
            <small>
              <ul>
                <li>Define the editing state as an atom that is passed via an argument. You can use <a href="https://github.com/calmm-js/karet.util/#U-atom">U.atom</a> from karet.util library instead of having to import kefir.atom only for Atom definition.</li>
                <li>Use <a href="https://github.com/calmm-js/karet.util/#U-view">U.view</a> to decompose the contact prop into name, phone and email values; it works with plain values as well as atoms (our contacts argument is a plain value for now).</li>
                <li>Use <a href="https://github.com/calmm-js/karet.util/#U-ifElse">U.ifElse</a> to determine whether the contact is being edited or not.</li>
              </ul>
            </small>
          </section>
          <section>
            <h3>Task 2</h3>
            <p>Re-factor the ContactList component so that it works even if it received contacts as an observable.</p>
            <small>
              <ul>
                <li><a href="https://github.com/calmm-js/karet.util#U-mapElems">U.mapElems</a> works with plain values as well. Our contacts prop is still a plain value for now.</li>
              </ul>
            </small>
          </section>
          <section>
            <h3>Task 3</h3>
            <p>Create a state atom to hold the contacts and pass the contacts element to ContactList component.</p>
            <small>
              <ul>
                <li>Use the existing plain state object as a default value for the atom.</li>
                <li>You can either use state.view(lens) or U.view(lens, state) to decompose the state atom. When using U.view you never need to worry whether the input is an atom or a plain value.</li>
                <li>
                  Show the value of the state atom in a HTML element so you can see how it changes. Add the following to the root App component:
                  <pre><code data-trim class="js">&lt;pre&gt;{U.stringify(state, null, 2)}&lt;/pre&gt;</code></pre>
                </li>
              </ul>
            </small>
          </section>
          <section>
            <h3>Task 4</h3>
            <p>Make the contacts actually editable.</p>
            <small>
              <ul>
                <li>By now you have decomposed state all the way down to the Contact component. Implement onChange handler for the text input to update the corresponding atom's value.</li>
                <li class="fragment">Alternatively you can use a convenient utility component <a href="https://github.com/calmm-js/karet.util/#U-Input">U.Input</a>.</li>
              </ul>
            </small>
          </section>
          <section>
            <h3>Task 5</h3>
            <p>Make the contacts deletable.</p>
            <small>
              <ul>
                <li>Atoms (and LensedAtoms) can easily be <a href="https://github.com/calmm-js/kefir.atom#remove">removed</a>.</li>
              </ul>
            </small>
          </section>
          <section>
            <h3>Task 6</h3>
            <p>Make it possible to add new contacts.</p>
            <small>
              <ul>
                <li>Append an object with default values for name, email and phone at the end of the contacts array in the state atom.</li>
              </ul>
            </small>
          </section>
          <section>
            <h3>Task 7</h3>
            <p>Display the total contact count somewhere.</p>
            <small>What was the first solution you came up with?</small>
          </section>
          <section>
            <h3>Task 8</h3>
            <p>Add <strong>"editing"</strong> class to the Contact component root element when editing.</p>
            <small>
              <ul>
                <li class="fragment">Tip: <a href="https://github.com/calmm-js/karet.util#U-cns">U.cns</a> is an useful utility function for this.</li>
                <li class="fragment">Tip: U.cns is lifted, so you can give observables as inputs. <a href="https://github.com/calmm-js/karet.util#U-when">U.when</a> is quite useful also.</li>
              </ul>
            </small>
          </section>
          <section>
            <h3>Task 9</h3>
            <p>Only allow one contact to be edited at one time.</p>
            <small>
              <ul>
                <li class="fragment">Tip: Persist the editing state of a contact in the contacts atom instead of component local state.</li>
                <li class="fragment">Tip: In the ContactList component create a derived computation which searches for a contact where the editing is set to true.</li>
              </ul>
            </small>
          </section>
          <section>
            <small>
              <h3>Bonus tasks</h3>
              <ol>
                <li class="fragment">Add a search text input and filter the visible contacts by it. Persist the search text value in the root atom. <a href="https://www.npmjs.com/package/partial.lenses#L-filter">L.filter</a> will be useful.</li>
                <li class="fragment">Add validation to the contact editing. Validate the email and phone number using the <a href="http://npmjs.com/package/partial.lenses.validation">partial.lenses.validation</a> library.</li>
                <li class="fragment">Persist the root contact atom in local storage using the <a href="http://npmjs.com/package/partial.lenses.validation">atom.storage</a> library.</li>
              </ol>
            </small>
          </section>
        </section>
        <section>
          <section>
            <h2>How to start using Calmm today</h2>
            <ul>
              <li class="fragment">You don't have to use everything</li>
              <li class="fragment">Join #calmm in Slack and calmm-js gitter for help</li>
              <li class="fragment">Easy to interop with existing apps, let's look at some examples</li>
            </ul>
          </section>
          <section>
            <small>
              <h2>Example: Passing observables to non-calmm components</h2>
              <pre class="fragment"><code data-trim class="jsx">
import * as React from 'karet'
import { Map } from '3rd-party-map'

&lt;Map position={currentPositionAtom} /&gt;
              </code></pre>
              <p class="fragment">React will throw an error if you try to pass an observable to the Map component, since it doesn't use karet/baret.</p>
              <p class="fragment">Easy way to fix this is using <strong>karet-lift</strong> attribute. <span class="fragment">If the Map component is used a lot, you can also create a lifted version of the component and use that.</span></p>
              <pre class="fragment"><code data-trim class="jsx">
import * as React from 'karet'
import * as U from 'karet.util'
import { Map } from '3rd-party-map'

const LiftedMap = React.fromClass(Map)
const LiftedMap2 = U.toKaret(Map) // this does the same<commit_msg>presentation changes<commit_after><!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

    <title>Calmm training</title>

    <link rel="stylesheet" href="css/reveal.css">
    <link rel="stylesheet" href="css/theme/black.css">

    <!-- Theme used for syntax highlighting of code -->
    <link rel="stylesheet" href="lib/css/zenburn.css">

    <!-- Printing and PDF exports -->
    <script>
      var link = document.createElement( 'link' );
      link.rel = 'stylesheet';
      link.type = 'text/css';
      link.href = window.location.search.match( /print-pdf/gi ) ? 'css/print/pdf.css' : 'css/print/paper.css';
      document.getElementsByTagName( 'head' )[0].appendChild( link );
    </script>
  </head>
  <body>
    <div class="reveal">
      <div class="slides">
        <section>
          <section>
            <h1>Calmm Training</h1>
            <p>https://rekotiira.github.io/calmm-training/</p>
            <small><NAME></small>
          </section>
          <section>
            <h2>Agenda</h2>
            <ul>
              <li class="fragment">Introduction to Calmm</li>
              <li class="fragment">Hands-on excercises</li>
              <li class="fragment">How to start using Calmm today</li>
              <li class="fragment">Benefits of Calmm</li>
              <li class="fragment">Painpoints with Calmm</li>
            </ul>
          </section>
        </section>
        <section>
          <h2>What is Calmm?</h2>
          <ul>
            <li class="fragment">An architecture and a collection of libraries</li>
            <li class="fragment">Declarative and boilerplate-free way to write reactive UIs</li>
            <li class="fragment">Some of the libraries are React specific but not all</li>
            <li class="fragment">State is observable. Dependent computations are observable. You can use either Bacon or Kefir.</li>
          </ul>
        </section>
        <section>
          <h2>How is it different from traditional React?</h2>
        </section>
        <section>
          <section>
            <h3>Observables are embedded directly in the VDOM</h3>
          </section>
          <section>
            <pre><code data-trim class="jsx">
  import * as React from 'baret' // or karet for Kefir

  const MyComponent = () => {
    const time = Bacon.once()
      .merge(Bacon.interval(1000))
      .map(() => new Date().toString())
      .toProperty()

    return &lt;div&gt;The time is &lt;strong&gt;{time}&lt;/strong&gt;&lt;/div&gt;
  }
            </code></pre>
            <p class="fragment">karet and baret hooks into the createElement API of React, which is the reason you need to import React from karet or baret library.</p>
          </section>
          <section>
            <h2>Embedding observables directly into VDOM has a lot of benefits</h2>
          </section>
          <section>
            <small>
              <h2>Completely boilerplate-free</h2>
              <ul>
                <li class="fragment">State is stored in modifiable and observable atoms (more about this in a minute)</li>
                <li class="fragment">No glue code needed to transform external state into props or internal React component state</li>
                <li class="fragment">
                  No need for
                  <pre><code data-trim class="js">
Bacon.combineTemplate({
  todos: todosProperty,
  counter: counterProperty
})
  .takeUntil(componentUnmountStream)
  .onValue(state => this.setState(state))
                  </code></pre>
                </li>
                <li class="fragment">
                  ... or ...
                  <pre><code data-trim class="js">
const mapStateToProps = (state, ownProps) => ({
  todos: state.todos,
  counter: state.counter
})
const mapDispatchToProps = ...
const WrappedComponent = connect(mapStateToProps, mapDispatchToProps)(TodoComponent)
                  </code></pre>
                </li>
                <li class="fragment">
                  ... etc.
                </li>
              </ul>
            </small>
          </section>
          <section>
            <small>
              <h2>Observable life-cycle is automatic</h2>
              <ul>
                <li class="fragment">Calmm subscribes to your observables when a component is mounted</li>
                <li class="fragment">... and unsubscribes when unmounted</li>
                <li class="fragment">
                  ... but only when the VDOM path is actually being rendered:
                  <pre class="fragment"><code data-trim>
const UselessComponent = ({ observable }) =>
  &lt;div&gt;
    {new Date().getFullYear() >= YEAR_OF_LINUX_DESKTOP
      ? observable
      : 'The year of the desktop linux desktop is not yet here'}
  &lt;/div&gt;
                  </code></pre>
                  <p class="fragment">observable is only subscribed to if the year of linux desktop has been reached.</p>
                </li>
                <li class="fragment">Enables you to lazily process dependent computations, which is very useful for expensive computations, or computations that may not need to be processed at all.</li>
                <li class="fragment">... and you get this without writing a single line of extra code.</li>
              </ul>
            </small>
          </section>
          <section>
            <small>
              <h2>When an observable changes only the relevant part of the VDOM is updated</h2>
              <pre class="fragment"><code data-trim>
  const MyComponent = ({ observable }) =>
    &lt;div&gt;
      &lt;ComplexComponent /&gt;
      The value of observable is: &lt;strong&gt;{observable}&lt;/strong&gt;
    &lt;/div&gt;
              </code></pre>
              <ul>
                <li class="fragment">When observable changes, only the strong element is re-rendered</li>
                <li class="fragment">Fast incremental VDOM updates</li>
                <li class="fragment">No need for shouldComponentUpdate</li>
                <li class="fragment">Eliminates need for render optimization in vast majority of cases</li>
                <li class="fragment">There are exceptions though</li>
              </ul>
            </small>
          </section>
          <section>
            <small>
              <h3>You can write your components using functional React components</h3>
              <ul>
                <li class="fragment">No need for createClass or React.Component</li>
                <li class="fragment">The function is only called once, on mount</li>
                <li class="fragment">Concise components, with a lot of the React boilerplate removed</li>
              </ul>
            </small>
          </section>
        </section>
        <section>
          <section>
            <h3>Component properties can either be values or observables</h3>
          </section>
          <section>
            <small>
              <h3>Example: working with values and observables</h3>
              <pre><code data-trim class="jsx">
const MultiplyByTwo = ({ number }) => &lt;div>{number * 2}&lt;/div&gt;
              </code></pre>
              <p class="fragment">Does not work with observables.</p>

              <pre class="fragment"><code data-trim class="jsx">
const MultiplyByTwo = ({ number }) => &lt;div&gt;{number.map(it => it * 2)}&lt;/div&gt;
              </code></pre>
              <p class="fragment">Does not work with plain values.</p>

              <pre class="fragment"><code data-trim class="jsx">
import * as U from 'karet.util'
import * as R from 'kefir.ramda'

const MultiplyByTwoA = ({ number }) => &lt;div&gt;{U.mapValue(it => it * 2, number)}&lt;/div&gt;
const MultiplyByTwoB = ({ number }) => &lt;div&gt;{R.multiply(number, 2)}&lt;/div&gt;
              </code></pre>
              <p class="fragment">Works with both!</p>
              <p class="fragment">U.mapValue and R.multiply are <strong>lifted</strong> to work with both plain values and observables.</p>
            </small>
          </section>
          <section>
            <small>
              <h3>Lifted functions</h3>
              <ul>
                <li class="fragment">If you have a function that works with plain values, <strong>lifting</strong> it means that the lifted version can accept plain values and observables as arguments.</li>
                <li class="fragment">When a lifted function is called with only plain values as arguments, the result is computed immediately and is also a plain value.</li>
                <li class="fragment">When any of the arguments is an observable, the result is an observable as well.</li>
                <li class="fragment"><strong>karet.util</strong> (and <strong>baret.util</strong>) contain a lot of useful utility functions, many of which are lifted.</li>
                <li class="fragment">Calmm also has a few wrapper libraries that lift the functions of the wrapped libraries, i.e. <strong>kefir.ramda</strong> and <strong>kefir.partial.lenses</strong>.</li>
                <li class="fragment">
                  It is easy to lift your own functions to work with observables:
                  <pre class="fragment"><code data-trim class="js">
import * as U from 'karet.util'

const includes = U.lift((xs, x) => xs.includes(x))
const obsOfBooleans = includes(obsOfArrays, obsOfValues)
                  </code></pre>
                </li>
              </ul>
            </small>
          </section>
          <section>
            <small>
              <h3>Examples of lifted utility functions in calmm</h3>
              <pre class="fragment"><code data-trim class="jsx">
const PositiveAndLessThan100 = ({ number }) =>
  &lt;div&gt;
    Is {number} positive and less than 100:
    {U.ifElse(
      U.and(R.gte(number, 0), R.lt(number, 100)),
      'yes',
      'no')}
  &lt;/div&gt;
              </code></pre>
              <p class="fragment">Also possible to write</p>
              <pre class="fragment"><code data-trim class="jsx">
const PositiveAndLessThan100 = ({ number }) =&gt; {
  const test = U.lift(number =&gt; number &gt;= 0 && number &lt; 100)
  return (
    &lt;div&gt;
      Is {number} positive and less than 100: {U.ifElse(test(number), 'yes', 'no')}
    &lt;/div&gt;
  )
}
              </code></pre>
              <p class="fragment">or</p>
              <pre class="fragment"><code data-trim class="jsx">
const PositiveAndLessThan100 = ({ number }) =>
  &lt;div&gt;
    Is {number} positive and less than 100:
    {U.mapValue(number =&gt; (number &gt;= 0 && number &lt; 100) ? 'yes' : 'no', number)}
  &lt;/div&gt;
              </code></pre>
              <p class="fragment">If you have complex conditions it is sometimes useful to break down the logic into a separate lifted function for readability.</p>
            </small>
          </section>
          <section>
            <small>
              <h3>Examples of lifted utility functions in calmm</h3>
              <ul>
                <li class="fragment">What you saw in the previous examples were examples of dependent computations.</li>
                <li class="fragment">When the inputs change, so do the outputs. The output can be a plain value, instance of a component, etc.</li>
                <li class="fragment">When the observables change, the dependent computations are re-run, keeping your UI consistent with your application state.</li>
                <li class="fragment">Even complex and asynchronous computations are quite trivial compared to many other tools.</li>
              </ul>
            </small>
          </section>
          <section>
            <small>
              <h3>Example of an asynchronous dependent computation</h3>
              <pre><code data-trim class="jsx">
const Search = ({ text = U.atom('') }) =&gt; {
  const getSearchUrl = text =&gt; `https://my.api/search?text=${encodeURIComponent(text)}`

  const results = U.thru(
    text,
    U.debounce(300),
    U.flatMapLatest(text =&gt; U.thru(
      U.fromPromise(() =&gt; fetch(getSearchUrl(text))),
      U.startWith(undefined)
    )),
    U.startWith([])
  )

  return (
    &lt;div&gt;
      &lt;U.Input value={text} /&gt;
      {U.ifElse(
        R.is(Array, results),
        &lt;ul&gt;
          {U.mapElems((result, i) =&gt; &lt;li key={i}&gt;{result}&lt;/li&gt;, results)}
        &lt;/ul&gt;,
        'Loading'
      )}
    &lt;/div&gt;
  )
}
              </code></pre>
            </small>
          </section>
        </section>
        <section>
          <section>
            <h2>Atoms</h2>
            <ul>
              <li class="fragment">Used to store state</li>
              <li class="fragment">Atoms are observable (properties)</li>
              <li class="fragment">Atoms are modifiable (modify / set)</li>
              <li class="fragment">Stored state is immutable data</li>
              <li class="fragment">Can be decomposed into smaller slices of state using lenses</li>
            </ul>
          </section>
          <section>
            <pre><code data-trim class="jsx">
const Counter = ({ count = Atom(0) }) =>
  &lt;span&gt;
    &lt;button onClick={() =&gt; count.modify(R.add(-1))}&gt;-&lt;/button&gt;
    {count}
    &lt;button onClick={() =&gt; count.modify(R.add(1))}&gt;+&lt;/button&gt;
  &lt;/span&gt;
            </code></pre>
            <small class="fragment">Having the count atom as a parameter makes it easy to use the component with local or global (external) state, making the component more composeable and flexible.</small>
            <pre class="fragment"><code data-trim class="jsx">
&lt;Counter /&gt;
            </code></pre>
            <pre class="fragment"><code data-trim class="jsx">
const count = Atom(10)
&lt;Counter count={count} /&gt;
            </code></pre>
          </section>
          <section>
            <h2>Lenses & lensed atoms</h2>
            <ul>
              <li class="fragment">Lensed atom is a subset of an atom that is decomposed with a lens</li>
              <li class="fragment">Lensed atoms are observable (properties)</li>
              <li class="fragment">Lensed atoms are modifiable (modify / set)</li>
              <li class="fragment">Can be decomposed into even smaller slices using lenses</li>
              <li class="fragment">Easily build a data structure that follows the structure of your UI</li>
            </ul>
          </section>
          <section>
            <small>
              <h3>Example: decompose state to child components</h3>
              <pre><code data-trim class="jsx">
const counters = Atom([0, 0, 0])

&lt;Counter count={counters.view(0)} /&gt;
&lt;Counter count={counters.view(1)} /&gt;
&lt;Counter count={counters.view(2)} /&gt;
              </code></pre>
            </small>
          </section>
          <section>
            <small>
              <h3>Example: filter a list to only show some elements</h3>
              <pre><code data-trim class="jsx">
const todos = Atom([
  { title: 'Wash laundry', finished: false },
  { title: 'Buy groceries', finished: true },
  { title: 'Clean kitchen', finished: false }
])

const TodoList = ({ todos }) =>
  &lt;div&gt;
    &lt;h2&gt;Todo&lt;/h2&gt;
    {U.mapElems(
      (todo, i) =&gt; &lt;TodoItem key={i} todo={todo} /&gt;,
      todos
    )}
  &lt;/div&gt;

const UnfinishedTodos = ({ todos }) => {
  const onlyUnfinishedLens = L.filter(todo => !todo.finished)
  return &lt;TodoList todos={todos.view(onlyUnfinishedLens)} /&gt;
}
              </code></pre>
            </small>
          </section>
          <section>
            <small>
              <h3>Example: change a value in an object</h3>
              <pre><code data-trim class="jsx">
const obj = Atom({
  foo: {
    bar: [1, 2, 3]
  }
})

// focus the 2nd element of the foo.bar array
const slice = obj.view(['foo', 'bar', 1])

slice.set(20)
obj.get() // { foo: { bar: [ 1, 20, 3 ] }}

slice.modify(R.multiply(2))
obj.get() // { foo: { bar: [ 1, 40, 3 ] }}
              </code></pre>
            </small>
          </section>
          <section>
            <small>
              <h3>Example: append a value to a list</h3>
              <pre><code data-trim class="jsx">
const list = Atom({ items: ['x', 'y'] })
list.modify(L.set(['items', L.append], 'z'))
list.get() // { items: ['x', 'y', 'z'] }
              </code></pre>
              <div class="fragment">
                Without the L.append
                <pre><code data-trim class="jsx">
const list = Atom({ items: ['x', 'y'] })
list.modify(L.set(['items'], 'z'))
list.get() // { items: 'z' }
                </code></pre>
              </div>
              <div class="fragment">
                For simple appends Ramda's R.append is usually simpler though
                <pre><code data-trim class="jsx">
const list = Atom(['x', 'y'])
list.modify(R.append('z')) // list.modify(L.set(L.append, 'z'))
list.get() // ['x', 'y', 'z']
                </code></pre>
              </div>
            </small>
          </section>
          <section>
            <small>
              <h3>Example: remove a value from a list</h3>
              <pre><code data-trim class="jsx">
const list = Atom(['x', 'y', 'z'])
list.modify(L.remove(1))
list.get() // ['x', 'z']
              </code></pre>
              <p class="fragment">Lensed atoms can also remove themselves</p>
              <pre class="fragment"><code data-trim class="jsx">
const list = Atom(['x', 'y', 'z'])
const item = list.view(1)
item.remove()
list.get() // ['x', 'z']
              </code></pre>
              <p class="fragment">This is a very useful pattern when you want to have removable UI components where the remove button is in the removable component itself.</p>
            </small>
          </section>
          <section>
            <small>
              <h3>Lenses/optics are very powerful, this is just scratching the surface</h3>
              <ul>
                <li class="fragment">Fetch data from API and transform into format that UI expects.</li>
                <li class="fragment">Make changes via UI, lenses are bidirectional so you can instantly PUT changes back to API. Just define the format of your data via lenses once.</li>
                <li class="fragment">Define default & required values.</li>
                <li class="fragment">Not just lenses. Traversals and isomorphisms.</li>
              </ul>
            </small>
          </section>
        </section>
        <section>
          <small>
            <h3>Calmm libraries we will be using today</h3>
            <ul>
              <li class="fragment"><strong>karet</strong> - embedding Kefir observables in React VDOM</li>
              <li class="fragment"><strong>kefir.atom</strong> - managing the state</li>
              <li class="fragment"><strong>karet.util</strong> - utilities for karet; today we are mainly interested in U.mapElems for easily iterating over an array of values in atom</li>
              <li class="fragment"><strong>partial.lenses</strong> - decomposing atoms with lenses</li>
            </ul>
          </small>
        </section>
        <section>
          <section>
            <h3>Excercise: a simple contact book React application</h3>
            <p class="fragment">Open <a href="https://codesandbox.io/s/4wyz1lo5y0" target="_blank">https://codesandbox.io/s/4wyz1lo5y0</a> in your browser and fork it.</p>
          </section>
          <section>
            <h3>Task 1</h3>
            <p>Re-factor the Contact component to a calmm-style component.</p>
            <small>
              <ul>
                <li>Define the editing state as an atom that is passed via an argument. You can use <a href="https://github.com/calmm-js/karet.util/#U-atom">U.atom</a> from karet.util library instead of having to import kefir.atom only for Atom definition.</li>
                <li>Use <a href="https://github.com/calmm-js/karet.util/#U-view">U.view</a> to decompose the contact prop into name, phone and email values; it works with plain values as well as atoms (our contacts argument is a plain value for now).</li>
                <li>Use <a href="https://github.com/calmm-js/karet.util/#U-ifElse">U.ifElse</a> to determine whether the contact is being edited or not.</li>
              </ul>
            </small>
          </section>
          <section>
            <h3>Task 2</h3>
            <p>Re-factor the ContactList component so that it works even if it received contacts as an observable.</p>
            <small>
              <ul>
                <li><a href="https://github.com/calmm-js/karet.util#U-mapElems">U.mapElems</a> works with plain values as well. Our contacts prop is still a plain value for now.</li>
              </ul>
            </small>
          </section>
          <section>
            <h3>Task 3</h3>
            <p>Create a state atom to hold the contacts and pass the contacts element to ContactList component.</p>
            <small>
              <ul>
                <li>Use the existing plain state object as a default value for the atom.</li>
                <li>You can either use state.view(lens) or U.view(lens, state) to decompose the state atom. When using U.view you never need to worry whether the input is an atom or a plain value.</li>
                <li>
                  Show the value of the state atom in a HTML element so you can see how it changes. Add the following to the root App component:
                  <pre><code data-trim class="js">&lt;pre&gt;{U.stringify(state, null, 2)}&lt;/pre&gt;</code></pre>
                </li>
              </ul>
            </small>
          </section>
          <section>
            <h3>Task 4</h3>
            <p>Make the contacts actually editable.</p>
            <small>
              <ul>
                <li>By now you have decomposed state all the way down to the Contact component. Implement onChange handler for the text input to update the corresponding atom's value.</li>
                <li class="fragment">Alternatively you can use a convenient utility component <a href="https://github.com/calmm-js/karet.util/#U-Input">U.Input</a>.</li>
              </ul>
            </small>
          </section>
          <section>
            <h3>Task 5</h3>
            <p>Make the contacts deletable.</p>
            <small>
              <ul>
                <li>Atoms (and LensedAtoms) can easily be <a href="https://github.com/calmm-js/kefir.atom#remove">removed</a>.</li>
              </ul>
            </small>
          </section>
          <section>
            <h3>Task 6</h3>
            <p>Make it possible to add new contacts.</p>
            <small>
              <ul>
                <li>Append an object with default values for name, email and phone at the end of the contacts array in the state atom.</li>
              </ul>
            </small>
          </section>
          <section>
            <h3>Task 7</h3>
            <p>Display the total contact count somewhere.</p>
            <small class="fragment">What was the first solution you came up with?</small>
          </section>
          <section>
            <h3>Task 8</h3>
            <p>Add <strong>"editing"</strong> class to the Contact component root element when editing.</p>
            <small>
              <ul>
                <li class="fragment">Tip: <a href="https://github.com/calmm-js/karet.util#U-cns">U.cns</a> is an useful utility function for this.</li>
                <li class="fragment">Tip: U.cns is lifted, so you can give observables as inputs. <a href="https://github.com/calmm-js/karet.util#U-when">U.when</a> is quite useful also.</li>
              </ul>
            </small>
          </section>
          <section>
            <h3>Task 9</h3>
            <p>Only allow one contact to be edited at one time.</p>
            <small>
              <ul>
                <li class="fragment">Tip: Persist the editing state of a contact in the contacts atom instead of component local state.</li>
                <li class="fragment">Tip: In the ContactList component create a derived computation which searches for a contact where the editing is set to true.</li>
              </ul>
            </small>
          </section>
          <section>
            <small>
              <h3>Bonus tasks</h3>
              <ol>
                <li class="fragment">Add a search text input and filter the visible contacts by it. Persist the search text value in the root atom. <a href="https://www.npmjs.com/package/partial.lenses#L-filter">L.filter</a> will be useful.</li>
                <li class="fragment">Persist the root contact atom in local storage using the <a href="http://npmjs.com/package/partial.lenses.validation">atom.storage</a> library.</li>
                <li class="fragment">Add validation to the contact editing. Validate the email and phone number using the <a href="http://npmjs.com/package/partial.lenses.validation">partial.lenses.validation</a> library.</li>
              </ol>
            </small>
          </section>
        </section>
        <section>
          <section>
            <h2>How to start using Calmm today</h2>
            <ul>
              <li class="fragment">You don't have to use everything</li>
              <li class="fragment">Join #calmm in Slack and calmm-js gitter for help</li>
              <li class="fragment">Easy to interop with existing apps, let's look at some examples</li>
            </ul>
          </section>
          <section>
            <small>
              <h2>Example: Passing observables to non-calmm components</h2>
              <pre class="fragment"><code data-trim class="jsx">
import * as React from 'karet'
import { Map } from '3rd-party-map'

&lt;Map position={currentPositionAtom} /&gt;
              </code></pre>
              <p class="fragment">React will throw an error if you try to pass an observable to the Map component, since it doesn't use karet/baret.</p>
              <p class="fragment">Easy way to fix this is using <strong>karet-lift</strong> attribute. <span class="fragment">If the Map component is used a lot, you can also create a lifted version of the component and use that.</span></p>
              <pre class="fragment"><code data-trim class="jsx">
import * as React from 'karet'
import * as U from 'karet.util'
import { Map } from '3rd-party-map'

const LiftedMap = React.fromClass(Map)
const LiftedMap2 = U.toKaret(Map) // this does the same
{'fraction_non_alphanumeric': 0.13616876617122137, 'fraction_numerical': 0.0066101342801563765, 'mean_word_length': 2.0035736570423732, 'pattern_counts': {'":': 0, '<': 1295, '<?xml version=': 0, '>': 1337, 'https://': 25, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3187350', 'n_tokens_mistral': 15523, 'n_tokens_neox': 14947, 'n_words': 4651}