React Native: Under the Hood

React Native: Under the Hood

09f29a1cb5a7c670532ba4bb1b224758?s=128

Alexander Kotliarskyi

June 09, 2015
Tweet

Transcript

  1. 2.

    Plan 1. Why native apps matter? 2. How ReactJS works

    3. Running ReactJS on native platforms
  2. 4.
  3. 5.
  4. 6.

    Building native apps is hard • Different stacks of technologies

    • No knowledge and code sharing • Slow iteration speed • Hard to scale
  5. 8.

    Web • Different stacks of technologies • No knowledge and

    code sharing • Slow iteration speed • Hard to scale HTML / CSS / JS Same code and tech F5 / ⌘R React!
  6. 9.

    Web apps on the phone are not great • Very

    hard to provide smooth experiences • Not designed for complex interactions • Impossible to embed native components
  7. 12.
  8. 14.
  9. 17.

    render()  {      return  (        

     div(              span(                  'Count:  '  +  b(this.state.count)              ),              button(                  'Add  +1'              )          )      )   }
  10. 18.

    render()  {      return  (        

     <div>              <span>                  Count:  <b>{this.state.count}</b>              </span>              <button>                  Add  +1              </button>          </div>      )   } HTML VirtualDOM
  11. 19.

    render()  {      return  (        

     <div>              <span>                  Count:  <b>{this.state.count}</b>              </span>              <button  onClick={()  =>  ???  }>                  Add  +1              </button>          </div>      )   }
  12. 20.

    TextView  text  =  (TextView)findViewByID(R.layout.label);   text.setText('10'); _label.text  =  @"10"; too

    complex Android Objective-C JavaScript document.getElementByID('count').children[1].innerHTML  =  '10';   $('#counter  b').html('10');
  13. 21.

    render()  {      var  count  =  this.state.count;    

     return  (          <div>              <span>                  Count:  <b>{count}</b>              </span>              <button  onClick={()  =>  ???  }>                  Add  +1              </button>          </div>      )   }
  14. 22.

    render()  {      var  count  =  this.state.count;    

     return  (          <div>              <span>                  Count:  <b>{count}</b>              </span>              <button  onClick={()  =>  this.setState({count:  count  +  1})}>                  Add  +1              </button>          </div>      )   } setState
  15. 23.
  16. 24.

         <div>              <span>

                     Count:  <b>9</b>              </span>              <button>                  Add  +1              </button>          </div>      <div>              <span>                  Count:  <b>10</b>              </span>              <button>                  Add  +1              </button>          </div> state  =  {count:  9} state  =  {count:  10} <b>9</b> <b>9</b> <b>10</b> findDOMNode(b).innerHTML  =  '10';
  17. 29.

    <div>   <span>   <img> <View>   <Text>   <Image>

    <ScrollView>   <MapView>   <TabBar>   <DatePicker>   ... Base components
  18. 46.

    Native Bridge JavaScript Event
 (touch, timer, networks, etc.) 1 Collect

    data and notify JS 2 Serialized payload 3 Process event 4 Call 0 – ∞ native methods 5 Update UI
 (if needed) 8 Serialized response 6 Process commands 7
  19. 49.
  20. 51.

       render()  {          return  (  

               <View  style={styles.container}>                  <Text  style={styles.value}>                      {this.state.count}                  </Text>                  <Button                      title="Add  +1"                      onPress={()  =>  this.inc()}                  />              </View>          );      }
  21. 52.

       inc()  {          var  newCount  =

     this.state.count  +  1;          this.setState({count:  newCount});          fetch(              'https://api.conunter.io/',              {                  method:  'post',                  body:  'value='  +  newCount              }          );      }
  22. 54.

    Native Bridge JavaScript [ 'EventEmitter', 'receiveTouches', ['end', {'x': 42, 'y':

    106}] ] [_bridge enqueueJSCall:@"RCTEventEmitter.receiveTouches" args:@[@"end", @{@"x": @42, @"y": @106}]]; call('EventEmitter',  'receiveTouches',  [{x:  42,  y:  ...}])
  23. 55.

    function  call(moduleName,  methodName,  args)  {      MessageQueue.init();    

           var  module  =  require(moduleName);      module[methodName].apply(module,  args);            return  MessageQueue.flush();   } //  EventEmitter //  receiveTouches Message
 queue
  24. 66.

       inc()  {          var  newCount  =

     this.state.count  +  1;          this.setState({count:  newCount});          fetch(              'https://api.conunter.io/',              {                  method:  'post',                  body:  'value='  +  newCount              }          );      }
  25. 67.

             <View  style={...}>        

             <Text  style={...}>                      42                  </Text>                  <Button                      title="Add  +1"                      onPress={...}                  />              </View>          <View  style={...}>                  <Text  style={...}>                      43                  </Text>                  <Button                      title="Add  +1"                      onPress={...}                  />              </View> 42 43
  26. 70.

    NativeModules.UIManager  =  {      ...      update:  function(viewID,

     attributes)  {          MessageQueue.push(              ['UIManager',  'update',  [viewID,  attributes]]          );      }      ...   }; Message
 queue UIManager
 update  ..
  27. 71.

       inc()  {          var  newCount  =

     this.state.count  +  1;          this.setState({count:  newCount});          fetch(              'https://api.conunter.io/',              {                  method:  'post',                  body:  'value='  +  newCount              }          );      } Message
 queue UIManager
 update  .. DataManager
 query    ....
  28. 72.

    function  call(moduleName,  methodName,  args)  {      MessageQueue.init();    

           var  module  =  require(moduleName);      module[methodName].apply(module,  args);            return  MessageQueue.flush();   } Message
 queue UIManager
 update  .. DataManager
 query    ....
  29. 73.

    Native Bridge JavaScript [UIManager updateView:18 props:@{@"text": @"43"}] [DataManager query:@"post" url:@"http://..."]

    [ ['UIManager', 'update', [18, {text: '43'}]], ['DataManager', 'query', ['post', 'http://...']] ] Message
 queue UIManager
 update  .. DataManager
 query    ....
  30. 74.

    Native [UIManager updateView:18 props:@{@"text": @"43"}] addUIBlock:^() { UILabel *label =

    viewRegistry[18]; label.text = @"43"; [label markAsDirty]; }
  31. 76.

    { margin: 20, borderBottomWidth: 2, flex: 1, alignContent: 'center', }

    { left: 120, top: 220, width: 60, height: 60, } Flexbox Coordinates
  32. 78.

    Native Bridge JavaScript Event
 (touch, timer, networks, etc.) 1 Collect

    data and notify JS 2 Serialized payload 3 Process event 4 Call 0 – ∞ native methods 5 Serialized response 6 Process commands 7 Update UI
 (if needed) 8
  33. 79.
  34. 80.
  35. 81.

    Native Bridge JavaScript Event
 (touch, timer, networks, etc.) 1 Update

    UI
 (if needed) 8 Collect data and notify JS 2 Serialized payload 3 Process event 4 Call 0 – ∞ native methods 5 Serialized response 6 Process commands 7
  36. 89.
  37. 90.
  38. 92.
  39. 93.