Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
React Native: Under the Hood
Search
Alexander Kotliarskyi
June 09, 2015
Programming
22k
31
Share
React Native: Under the Hood
Alexander Kotliarskyi
June 09, 2015
More Decks by Alexander Kotliarskyi
See All by Alexander Kotliarskyi
Building Stellar User Experiences with React Native
frantic
2
1.1k
React Native Tutorial - NYC'15
frantic
5
1.4k
Other Decks in Programming
See All in Programming
Lightning-Fast Method Calls with Ruby 4.1 ZJIT / RubyKaigi 2026
k0kubun
1
200
PHP で mp3 プレイヤーを実装しよう
m3m0r7
PRO
0
270
PDI: Como Alavancar Sua Carreira e Seu Negócio
marcelgsantos
0
120
10 Tips of AWS ~Gen AI on AWS~
licux
5
380
How We Benchmarked Quarkus: Patterns and anti-patterns
hollycummins
1
130
AIエージェントで業務改善してみた
taku271
0
520
[RubyKaigi 2026] Require Hooks
palkan
0
120
セグメントとターゲットを意識するプロポーザルの書き方 〜採択の鍵は、誰に刺すかを見極めるマーケティング戦略にある〜
m3m0r7
PRO
0
520
JAWS-UG横浜 #100 祝・第100回スペシャルAWS は VPC レスの時代へ
maroon1st
0
130
10年分の技術的負債、完済へ ― Claude Code主導のAI駆動開発でスポーツブルを丸ごとリプレイスした話
takuya_houshima
0
2.5k
Codex CLIのSubagentsによる並列API実装 / Parallel API Implementation with Codex CLI Subagents
takatty
2
920
The Monolith Strikes Back: Why AI Agents ❤️ Rails Monoliths
serradura
0
320
Featured
See All Featured
Facilitating Awesome Meetings
lara
57
6.8k
Skip the Path - Find Your Career Trail
mkilby
1
110
SEOcharity - Dark patterns in SEO and UX: How to avoid them and build a more ethical web
sarafernandez
0
170
Bootstrapping a Software Product
garrettdimon
PRO
307
120k
Building a Modern Day E-commerce SEO Strategy
aleyda
45
9k
The browser strikes back
jonoalderson
0
970
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
49
9.9k
Leveraging Curiosity to Care for An Aging Population
cassininazir
1
220
Claude Code のすすめ
schroneko
67
220k
A better future with KSS
kneath
240
18k
The agentic SEO stack - context over prompts
schlessera
0
740
How to build an LLM SEO readiness audit: a practical framework
nmsamuel
1
710
Transcript
React Native: Under the hood Alex Kotliarskyi Facebook
Plan 1. Why native apps matter? 2. How ReactJS works
3. Running ReactJS on native platforms
Why do we ❤ native apps?
Native Apps • Fast, responsive • Complex gestures and smooth
animations • Consistent with platform
None
Building native apps is hard • Different stacks of technologies
• No knowledge and code sharing • Slow iteration speed • Hard to scale
Web got this right
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!
Web apps on the phone are not great • Very
hard to provide smooth experiences • Not designed for complex interactions • Impossible to embed native components
Development experience Awesome apps
React Native
None
UI = ƒ*(data) * No side effects
None
UI = ƒ(count)
UI = ƒ(count) = div( span('Count ' + count), button('Add
+1') )
render() { return (
div( span( 'Count: ' + b(this.state.count) ), button( 'Add +1' ) ) ) }
render() { return (
<div> <span> Count: <b>{this.state.count}</b> </span> <button> Add +1 </button> </div> ) } HTML VirtualDOM
render() { return (
<div> <span> Count: <b>{this.state.count}</b> </span> <button onClick={() => ??? }> Add +1 </button> </div> ) }
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');
render() { var count = this.state.count;
return ( <div> <span> Count: <b>{count}</b> </span> <button onClick={() => ??? }> Add +1 </button> </div> ) }
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
setState
<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';
Components Browser DOM UIKit Components Components Components VirtualDOM
1. Runtime 2.Base components 3. Calling native functions
ECMAScript 5
JavaScript Core • Part of WebKit project • Open Source
• Ships with iOS Runtime
<div> <span> <img> <View> <Text> <Image>
<ScrollView> <MapView> <TabBar> <DatePicker> ... Base components
create(view, parent, attributes)* update(view, attributes) delete(view) * actually React is
more complex that that
Just call native functions? nope
Synchronous
Native Method JavaScript time Waiting…
JavaScript time Native JavaScript Native
Synchronous Asynchronous
Overhead of every native call
JavaScript time
time JavaScript
Overhead of every native call Batch native calls
Shared mutable data
Native Objects JavaScript Objects
Shared mutable data Exchange serializable messages
Asynchronous Batched Serializable
The Bridge
Native Bridge JavaScript
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
JS is event-driven
Events Commands
Example
• Updates counter • Sends data to web service
render() { return (
<View style={styles.container}> <Text style={styles.value}> {this.state.count} </Text> <Button title="Add +1" onPress={() => this.inc()} /> </View> ); }
inc() { var newCount =
this.state.count + 1; this.setState({count: newCount}); fetch( 'https://api.conunter.io/', { method: 'post', body: 'value=' + newCount } ); }
Native UITouch [_bridge enqueueJSCall:@"EventEmitter.receiveTouches" args:@[@"end", @{@"x": @42, @"y": @106}]]; x,
y, view, ...
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: ...}])
function call(moduleName, methodName, args) { MessageQueue.init();
var module = require(moduleName); module[methodName].apply(module, args); return MessageQueue.flush(); } // EventEmitter // receiveTouches Message queue
Touch processing
What element should respond to a given event?
Button Button pressed!
Button Cancelled
Button Cancelled Scrollview
Button Scrolling stops Scrollview
Button Scrollview Horizontal Scrollview Navigator
Responder System
onStartShouldSetResponder onResponderTerminationRequest onResponderGrant onResponderMove onResponderRelease onResponderTerminate …
<TouchableOpacity> <TouchableHighlight> <TouchableBounce> <TouchableWithoutFeedback> onPress
inc() { var newCount =
this.state.count + 1; this.setState({count: newCount}); fetch( 'https://api.conunter.io/', { method: 'post', body: 'value=' + newCount } ); }
<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
var UIManager = require('NativeModules').UIManager; UIManager.update(18, {text: '43'}); Somewhere in
React's internals:
NativeModules
NativeModules.UIManager = { ... update: function(viewID,
attributes) { MessageQueue.push( ['UIManager', 'update', [viewID, attributes]] ); } ... }; Message queue UIManager update ..
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 ....
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 ....
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 ....
Native [UIManager updateView:18 props:@{@"text": @"43"}] addUIBlock:^() { UILabel *label =
viewRegistry[18]; label.text = @"43"; [label markAsDirty]; }
Layout Layout github.com/facebook/css-layout
{ margin: 20, borderBottomWidth: 2, flex: 1, alignContent: 'center', }
{ left: 120, top: 220, width: 60, height: 60, } Flexbox Coordinates
• User taps the button • Counter is updated
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
Benefits
Fast
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
Record / Replay
Flexible JS runtime
Native Bridge JavaScript
Native Bridge JavaScript Awesome App
Native Bridge JavaScript Awesome App WebKit process IPC
Native Bridge JavaScript Awesome App Chrome Debugger WebSockets
Live demo iPhone -> Chrome
None
None
Heroku iPhone
Streaming
None
UI = ƒ(data)
Thank you! github.com/frantic/tlv-2015 @alex_frantic