<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>React on David Mohl</title>
    <link>https://david.coffee/tags/react/</link>
    <description>Recent content in React on David Mohl</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <lastBuildDate>Thu, 19 Nov 2015 11:01:23 +0000</lastBuildDate><atom:link href="https://david.coffee/tags/react/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Demand driven iOS apps with om and react native</title>
      <link>https://david.coffee/demand-driven-ios-apps-with-om-and-react-native/</link>
      <pubDate>Thu, 19 Nov 2015 11:01:23 +0000</pubDate>
      
      <guid>https://david.coffee/demand-driven-ios-apps-with-om-and-react-native/</guid><description>&lt;p&gt;I recently talked a lot about om and react native. Since people seemed quite interested in this topic, I decided to hold a little presentation at the last Tokyo iOS meetup in November.&lt;/p&gt;
&lt;p&gt;People were a bit overwhelmed (many never saw clojurescript before) but the general feedback was quite good. I am sure I convinced at least 1 person to give it a spin!&lt;/p&gt;
&lt;p&gt;In any way, here is my talk from that iOS meetup. Slides are available &lt;a href=&#34;http://www.slideshare.net/dvcrn/demand-driven-applications-with-omnext-and-react-native-55185632&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;video-wrapper&#34;&gt;
&lt;iframe width=&#34;560&#34; height=&#34;315&#34; src=&#34;https://www.youtube.com/embed/oJ8t8Hc9XaE&#34; frameborder=&#34;0&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;This was also the first time we decided to record things so excuse the mediocore quality. I experimented by putting a external microphone on the table next to me but didn&amp;rsquo;t realise that the macbook fan blowed straight into it. Still slightly better than the in-camera mic but still room for improvements.&lt;/p&gt;
&lt;p&gt;I for my part am very excited about clojurescript on native and super happy to be part of this still young but growing community. Clojurescript will come for you - if you want it or not. Better start learning it now! 😈&lt;/p&gt;
</description>
      <content:encoded><![CDATA[<p>I recently talked a lot about om and react native. Since people seemed quite interested in this topic, I decided to hold a little presentation at the last Tokyo iOS meetup in November.</p>
<p>People were a bit overwhelmed (many never saw clojurescript before) but the general feedback was quite good. I am sure I convinced at least 1 person to give it a spin!</p>
<p>In any way, here is my talk from that iOS meetup. Slides are available <a href="http://www.slideshare.net/dvcrn/demand-driven-applications-with-omnext-and-react-native-55185632">here</a>.</p>
<div class="video-wrapper">
<iframe width="560" height="315" src="https://www.youtube.com/embed/oJ8t8Hc9XaE" frameborder="0" allowfullscreen></iframe>
</div>
<p>This was also the first time we decided to record things so excuse the mediocore quality. I experimented by putting a external microphone on the table next to me but didn&rsquo;t realise that the macbook fan blowed straight into it. Still slightly better than the in-camera mic but still room for improvements.</p>
<p>I for my part am very excited about clojurescript on native and super happy to be part of this still young but growing community. Clojurescript will come for you - if you want it or not. Better start learning it now! 😈</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Going native with om.next</title>
      <link>https://david.coffee/going-native-with-om.next/</link>
      <pubDate>Tue, 27 Oct 2015 12:47:46 +0000</pubDate>
      
      <guid>https://david.coffee/going-native-with-om.next/</guid><description>&lt;p&gt;I mentioned already earlier that I believe &lt;a href=&#34;https://github.com/omcljs/om&#34;&gt;om.next&lt;/a&gt; will be the future. Not particular om itself but the idea it implements: demand driven applications. The component declares what data it needs and the server is just there for delivering it. Components don&amp;rsquo;t want to coordinate 20 ajax requests just to gather all the data they need to operate. Components also don&amp;rsquo;t need all of the data your API provides in most cases, so why even the need to download all of it?&lt;/p&gt;
&lt;p&gt;These concepts make sense as the next iteration of server / client architectures but you know where they fit even better? &lt;strong&gt;Mobile Apps!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Especially when load time is critical and data volume limited, downloading big chunks of REST json data can get very annoying. We can&amp;rsquo;t just pump all the jsons our website uses into an app and expect it to be as performant as the web counterpart.&lt;/p&gt;
&lt;p&gt;So, wouldn&amp;rsquo;t it be amazing if our app just says &lt;em&gt;&amp;ldquo;I need the list of available books, but only the title and the image url and nothing else&amp;rdquo;&lt;/em&gt; and it will get exactly that and nothing more?&lt;/p&gt;
&lt;p&gt;With &lt;a href=&#34;https://github.com/omcljs/om&#34;&gt;next&lt;/a&gt; around the corner I decided to give it a try with react native. &lt;a href=&#34;http://cljsrn.org/&#34;&gt;cljsrn&lt;/a&gt; is already bundling a good amount of resources around the topic clojurescript and react native and &lt;a href=&#34;https://github.com/dmotz/natal&#34;&gt;natal&lt;/a&gt; and &lt;a href=&#34;http://cljsrn.org/ambly.html&#34;&gt;ambly&lt;/a&gt; already work great for legacy om, so let&amp;rsquo;s make it work for om.next!&lt;/p&gt;
&lt;h3 id=&#34;a-stoney-path&#34;&gt;A stoney path&lt;/h3&gt;
&lt;p&gt;After poking a bit around with next and natal, I quickly ran into a deadend because of it&amp;rsquo;s dependency to &lt;code&gt;gdom&lt;/code&gt; and &lt;code&gt;ReactDOM&lt;/code&gt;. Instead of calling &lt;code&gt;React.render&lt;/code&gt;, om.next relies on React 0.14 which splits the rendering logic from the component. Here we&amp;rsquo;re calling &lt;code&gt;ReactDOM.render&lt;/code&gt; instead, which, well, relies on a DOM.&lt;/p&gt;
&lt;p&gt;Luckily after a short chat with &lt;a href=&#34;https://github.com/swannodette&#34;&gt;@dnolen&lt;/a&gt; he promptly stripped out &lt;code&gt;ReactDOM&lt;/code&gt; (and &lt;code&gt;gdom&lt;/code&gt; as well) and added functionality that allows us to pass a &lt;code&gt;:root-render&lt;/code&gt; and &lt;code&gt;:root-unmount&lt;/code&gt; function into the reconciler. Whatever we specify here will get used to render and unmount components.&lt;/p&gt;
&lt;p&gt;Reading through the &lt;a href=&#34;https://github.com/facebook/react-native/tree/master/Libraries/ReactNative&#34;&gt;react native source&lt;/a&gt; made it clear that 0.14 has not been adapted yet and the rendering and unmounting logic is still inside &lt;code&gt;React&lt;/code&gt;. To plug this into om.next, all we have to do is&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-cljs&#34; data-lang=&#34;cljs&#34;&gt;:root-render #(.render js/React %1 %2)
:root-unmount #(.unmountComponentAtNode js/React %)})
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;em&gt;&amp;hellip;where js/React is the required react-native library.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Another thing that becomes clear is that React Native doesn&amp;rsquo;t render components into DOM references. Instead, it &lt;a href=&#34;https://github.com/facebook/react-native/blob/master/Libraries/ReactNative/ReactNative.js#L74-L80&#34;&gt;uses a number&lt;/a&gt; that references back to a component. With the first one being &lt;code&gt;1&lt;/code&gt;, we know exactly what where we have to add our root to:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-cljs&#34; data-lang=&#34;cljs&#34;&gt;(om/add-root! reconciler my-component 1)
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;wrapping-up&#34;&gt;Wrapping up&lt;/h3&gt;
&lt;p&gt;
&lt;img class=&#34;img-fluid&#34; src=&#34;./om.next-native.png&#34; alt=&#34;showcase&#34; /&gt;

&lt;/p&gt;
&lt;p&gt;The full code looks something like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-cljs&#34; data-lang=&#34;cljs&#34;&gt;;; Need to set js/React first so that Om can load
(set! js/React (js/require &amp;#34;react-native/Libraries/react-native/react-native.js&amp;#34;))

(ns future-next.core
  (:require [om.next :as om :refer-macros [defui]]))

;; Reset js/React back as the form above loads in an different React
(set! js/React (js/require &amp;#34;react-native/Libraries/react-native/react-native.js&amp;#34;))

;; Setup some methods to help create React Native elements
(defn view [opts &amp;amp; children]
  (apply js/React.createElement js/React.View (clj-&amp;gt;js opts) children))

(defn text [opts &amp;amp; children]
  (apply js/React.createElement js/React.Text (clj-&amp;gt;js opts) children))


;; Set up our Om UI
(defonce app-state (atom {:app/msg &amp;#34;Hello om.next!&amp;#34;}))

(defui WidgetComponent
  static om/IQuery
  (query [this]
         &amp;#39;[:app/msg])
  Object
  (render [this]
          (let [{:keys [app/msg]} (om/props this)]
            (view {:style {:flexDirection &amp;#34;column&amp;#34; :margin 40}}
                  (text nil msg))
            )))

 (defn read
   [{:keys [state] :as env} key params]
   (let [st @state]
     (if-let [[_ v] (find st key)]
       {:value v}
       {:value :not-found})))

 (def reconciler
   (om/reconciler
    {:state app-state
     :parser (om/parser {:read read})
     :root-render #(.render js/React %1 %2)
     :root-unmount #(.unmountComponentAtNode js/React %)})
   )

(om/add-root! reconciler WidgetComponent 1)

(defn ^:export init []
  ((fn render []
     (.requestAnimationFrame js/window render))))
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;a href=&#34;https://github.com/dmotz/natal/pull/18&#34;&gt;I submitted a PR&lt;/a&gt; to natal and once that&amp;rsquo;s merged in, all you have to do is &lt;code&gt;natal init&lt;/code&gt; :)&lt;/p&gt;
&lt;p&gt;Can you believe that all of this happened in just 1.5 days?&lt;/p&gt;
</description>
      <content:encoded><![CDATA[<p>I mentioned already earlier that I believe <a href="https://github.com/omcljs/om">om.next</a> will be the future. Not particular om itself but the idea it implements: demand driven applications. The component declares what data it needs and the server is just there for delivering it. Components don&rsquo;t want to coordinate 20 ajax requests just to gather all the data they need to operate. Components also don&rsquo;t need all of the data your API provides in most cases, so why even the need to download all of it?</p>
<p>These concepts make sense as the next iteration of server / client architectures but you know where they fit even better? <strong>Mobile Apps!</strong></p>
<p>Especially when load time is critical and data volume limited, downloading big chunks of REST json data can get very annoying. We can&rsquo;t just pump all the jsons our website uses into an app and expect it to be as performant as the web counterpart.</p>
<p>So, wouldn&rsquo;t it be amazing if our app just says <em>&ldquo;I need the list of available books, but only the title and the image url and nothing else&rdquo;</em> and it will get exactly that and nothing more?</p>
<p>With <a href="https://github.com/omcljs/om">next</a> around the corner I decided to give it a try with react native. <a href="http://cljsrn.org/">cljsrn</a> is already bundling a good amount of resources around the topic clojurescript and react native and <a href="https://github.com/dmotz/natal">natal</a> and <a href="http://cljsrn.org/ambly.html">ambly</a> already work great for legacy om, so let&rsquo;s make it work for om.next!</p>
<h3 id="a-stoney-path">A stoney path</h3>
<p>After poking a bit around with next and natal, I quickly ran into a deadend because of it&rsquo;s dependency to <code>gdom</code> and <code>ReactDOM</code>. Instead of calling <code>React.render</code>, om.next relies on React 0.14 which splits the rendering logic from the component. Here we&rsquo;re calling <code>ReactDOM.render</code> instead, which, well, relies on a DOM.</p>
<p>Luckily after a short chat with <a href="https://github.com/swannodette">@dnolen</a> he promptly stripped out <code>ReactDOM</code> (and <code>gdom</code> as well) and added functionality that allows us to pass a <code>:root-render</code> and <code>:root-unmount</code> function into the reconciler. Whatever we specify here will get used to render and unmount components.</p>
<p>Reading through the <a href="https://github.com/facebook/react-native/tree/master/Libraries/ReactNative">react native source</a> made it clear that 0.14 has not been adapted yet and the rendering and unmounting logic is still inside <code>React</code>. To plug this into om.next, all we have to do is</p>
<pre tabindex="0"><code class="language-cljs" data-lang="cljs">:root-render #(.render js/React %1 %2)
:root-unmount #(.unmountComponentAtNode js/React %)})
</code></pre><p><em>&hellip;where js/React is the required react-native library.</em></p>
<p>Another thing that becomes clear is that React Native doesn&rsquo;t render components into DOM references. Instead, it <a href="https://github.com/facebook/react-native/blob/master/Libraries/ReactNative/ReactNative.js#L74-L80">uses a number</a> that references back to a component. With the first one being <code>1</code>, we know exactly what where we have to add our root to:</p>
<pre tabindex="0"><code class="language-cljs" data-lang="cljs">(om/add-root! reconciler my-component 1)
</code></pre><h3 id="wrapping-up">Wrapping up</h3>
<p>
<img class="img-fluid" src="./om.next-native.png" alt="showcase" />

</p>
<p>The full code looks something like this:</p>
<pre tabindex="0"><code class="language-cljs" data-lang="cljs">;; Need to set js/React first so that Om can load
(set! js/React (js/require &#34;react-native/Libraries/react-native/react-native.js&#34;))

(ns future-next.core
  (:require [om.next :as om :refer-macros [defui]]))

;; Reset js/React back as the form above loads in an different React
(set! js/React (js/require &#34;react-native/Libraries/react-native/react-native.js&#34;))

;; Setup some methods to help create React Native elements
(defn view [opts &amp; children]
  (apply js/React.createElement js/React.View (clj-&gt;js opts) children))

(defn text [opts &amp; children]
  (apply js/React.createElement js/React.Text (clj-&gt;js opts) children))


;; Set up our Om UI
(defonce app-state (atom {:app/msg &#34;Hello om.next!&#34;}))

(defui WidgetComponent
  static om/IQuery
  (query [this]
         &#39;[:app/msg])
  Object
  (render [this]
          (let [{:keys [app/msg]} (om/props this)]
            (view {:style {:flexDirection &#34;column&#34; :margin 40}}
                  (text nil msg))
            )))

 (defn read
   [{:keys [state] :as env} key params]
   (let [st @state]
     (if-let [[_ v] (find st key)]
       {:value v}
       {:value :not-found})))

 (def reconciler
   (om/reconciler
    {:state app-state
     :parser (om/parser {:read read})
     :root-render #(.render js/React %1 %2)
     :root-unmount #(.unmountComponentAtNode js/React %)})
   )

(om/add-root! reconciler WidgetComponent 1)

(defn ^:export init []
  ((fn render []
     (.requestAnimationFrame js/window render))))
</code></pre><p><a href="https://github.com/dmotz/natal/pull/18">I submitted a PR</a> to natal and once that&rsquo;s merged in, all you have to do is <code>natal init</code> :)</p>
<p>Can you believe that all of this happened in just 1.5 days?</p>
]]></content:encoded>
    </item>
    
  </channel>
</rss>
