Cross Platform
Development
with React Native
Ken Wheeler | @ken_wheeler
What is React
Native?
Cross platform native app library
Write native apps in Javascript
Renders to real native UI
First, lets talk
about React
UI library developed at Facebook
Pitched as "just the view layer"
Robust component system
Virtual DOM
The new hotness
class Test extends React.Component {
render() {
return (
<div>
<p>I'm a component!</p>
</div>
)
}
}
JSX
<div>
<p>I'm a component!</p>
</div>
React.DOM.div(null,
React.DOM.p(null, "I'm a component!")
);
Props
class Test extends React.Component {
render() {
return <p>{this.props.name}</p>
}
}
//Usage
<Test name="Ken"/>
Prop Validation
Test.propTypes = {
name: PropTypes.string
};
Test.defaultProps = {
name: "Default"
};
State
class Test extends React.Component {
state = {
count: 1
};
render() {
return <p>{this.state.count}</p>
}
}
setState
this.setState({
count: 2
});
Events
class Test extends React.Component {
increment() { ... }
render() {
return (
<button onClick={this.increment}>
Increment
</button>
);
}
}
Component
Lifecycle
componentWillMount
componentDidMount
componentWillUnmount
componentWillReceiveProps
componentWillUpdate
componentDidUpdate
shouldComponentUpdate
What about data?
Unidirectional Data Flow
Flux Architecture
Smart Components
Redux
https://github.com/reactjs/redux
Relay
https://github.com/facebook/relay
RxJS
https://github.com/ReactiveX/RxJS
React Native
Why use React Native?
Cross Platform
"Native Feel"
One Language
Live Reload
OTA Updates
Why is makes sense for
business
Fast Development Cycles
Fast Deployment Cycle
Resource Interoperability
One Team
How React Native Works
Primitives
class Test extends React.Component {
render() {
return (
<View>
<Text>I'm a component!</Text>
</View>
)
}
}
View Components
View
Text
Image
ListView
MapView
Navigator
ScrollView
Modal
Picker
RefreshControl
Switch
TextInput
WebView
Touchable*
Device APIs
Alert
Animated
AppState
AsyncStorage
CameraRoll
Dimensions
Linking
NetInfo
PixelRatio
PanResponder
StyleSheet
LayoutAnimation
Poly lls
Flexbox
Geolocation
Network
Timers
Colors
Networking
Fetch
fetch(API_URL)
.then(res => res.json())
.then(data => {
console.log(data);
})
.catch(error => {
console.warn(error);
});
Async/Await
async function getData() {
try {
const res = await fetch(API_URL);
const data = await res.json();
console.log(data);
} catch(e) {
console.warn(e)
}
}
Styling & Layout
StyleSheet
const styles = StyleSheet.create({
container: {
backgroundColor: "#ccc",
padding: 10,
margin: 10,
borderRadius: 3,
borderWidth: 2
}
});
Applying Styles
class Container extends React.Component {
render() {
return (
<View
style={styles.container}/>
//... child components
</View>
)
}
}
Flexbox
const styles = StyleSheet.create({
layout: {
flexDirection: "row",
alignItems: "center",
justifyContent: "center"
},
tiles: {
flex: 1
}
});
Custom iOS
Modules
// MyModule.h
#import "RCTBridgeModule.h"
@interface MyModule : NSObject <RCTBridgeModule>
@end
// MyModule.m
@implementation MyModule
RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(sayName:(NSString *)name)
{
RCTLogInfo(@"My name is %@", name);
}
@end
// Usage in Javascript:
NativeModules.MyModule.sayName("Ken");
RCT_EXPORT_METHOD(getData:(RCTResponseSenderBlock)callback)
{
NSArray *data = ...
callback(@[data]);
}
// Usage in Javascript:
NativeModules.MyModule.getData(data => {
console.log(data);
});
RCT_REMAP_METHOD(getData,
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{
NSArray *data = ...
if (data) {
resolve(data);
} else {
NSError *error = ...
reject(@"no_data", @"Data fetch error", data);
}
}
// Usage in Javascript:
NativeModules.MyModule.getData
.then(data => console.log(data))
.catch(err => console.log(err));
Custom Android
Modules
public class MyModule extends ReactContextBaseJavaModule {
public MyModule(ReactApplicationContext reactContext) {
super(reactContext);
}
@Override
public String getName() {
return "MyModule";
}
@ReactMethod
public void sayName(String name) {
Log.v("MyModule", "My name is " + name);
}
}
// Usage in Javascript:
NativeModules.MyModule.sayName("Ken");
@ReactMethod
public void getData(Callback errorCallback, Callback successCallba
try {
float data = // ...get data;
successCallback.invoke(data);
} catch (IllegalViewOperationException e) {
errorCallback.invoke(e.getMessage());
}
}
// Usage in Javascript:
NativeModules.MyModule.getData(
(err) => console.log(err),
(data) => console.log(data)
);
@ReactMethod
public void getData(Promise promise) {
try {
float data = // ...get data;
promise.resolve(data);
} catch (IllegalViewOperationException e) {
promise.reject(e);
}
}
// Usage in Javascript:
NativeModules.MyModule.getData
.then(data => console.log(data))
.catch(err => console.log(err));
iOS View
Components
@interface RCTMapView : RCTViewManager
@end
@implementation RCTMapManager
RCT_EXPORT_MODULE()
RCT_EXPORT_VIEW_PROPERTY(mapType, MKMapType)
- (UIView *)view
{
return [[MKMapView alloc] init];
}
@end
//Usage in javascript
const RCTMap = requireNativeComponent('RCTMap', null);
Android View
Components
public class ReactMapManager extends SimpleViewManager<MapView>
@Override
public String getName() {
return "RCTMapView";
}
@ReactProp(name = "mapType")
public void setMapType(ReactMapView view, @Nullable int mapType
googleMap.getMap().setMapType(mapType);
}
@Override
public ReactMapView createViewInstance(ThemedReactContext contex
return new MapView(context, Fresco.newDraweeControllerBuilder
}
}
//Usage in javascript
const RCTMap = requireNativeComponent('RCTMap', null);
React Native
Tooling
Debugging
Chrome Devtools
Nuclide
Redbox
Yellowbox
Pro ling
Systrace
Perf Monitor
Instruments (iOS)
JS Tooling
ES6
const add = (a, b) => a + b; // Arrow functions
let { name, address, ...info } = this.props; // Destructuring
let state = { // Object rest spreads
...state,
name
};
class Test { // ES6 Classes
getName() {
return "Test";
}
}
Flowtype
function getData(url: string, callback: Function): Object {
return fetch(url)
.then(res => res.json())
.then(data => callback(data));
}
Testing
Mocha/Jest
react-addons-test-utils
Enzyme
react-native-mock
Appium
Third Party
Tooling
AppHub
CodePush
Reindex
AppBoy
RNPM
Om & Elm Native
ExponentJS
No Xcode required
Distribute apps to anyone with the
app
Exponent XDE
Exponent App
Available in the App Store
Demo
exp://exp.host/@thekenwheeler/mobile-day-demo

Mobile Day - React Native