Mobile Day - React Native

Preview:

Citation preview

Cross PlatformDevelopmentwith React NativeKen Wheeler | @ken_wheeler

What is ReactNative?

Cross platform native app library

Write native apps in Javascript

Renders to real native UI

First, lets talkabout 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!") );

Propsclass Test extends React.Component { render() { return <p>{this.props.name}</p> } } //Usage <Test name="Ken"/>

Prop ValidationTest.propTypes = { name: PropTypes.string }; Test.defaultProps = { name: "Default" };

Stateclass Test extends React.Component { state = { count: 1 }; render() { return <p>{this.state.count}</p> } }

setStatethis.setState({ count: 2 });

Eventsclass Test extends React.Component { increment() { ... } render() { return ( <button onClick={this.increment}> Increment </button> ); } }

ComponentLifecycle

componentWillMountcomponentDidMountcomponentWillUnmount

componentWillReceivePropscomponentWillUpdatecomponentDidUpdateshouldComponentUpdate

What about data?

Unidirectional Data Flow

Flux Architecture

Smart Components

Reduxhttps://github.com/reactjs/redux

Relayhttps://github.com/facebook/relay

RxJShttps://github.com/ReactiveX/RxJS

React Native

Why use React Native?

Cross Platform

"Native Feel"

One Language

Live Reload

OTA Updates

Why is makes sense forbusiness

Fast Development Cycles

Fast Deployment Cycle

Resource Interoperability

One Team

How React Native Works

Primitivesclass Test extends React.Component { render() { return ( <View> <Text>I'm a component!</Text> </View> ) } }

View Components

ViewTextImageListViewMapViewNavigatorScrollView

ModalPicker

RefreshControlSwitchTextInputWebViewTouchable*

Device APIs

AlertAnimatedAppState

AsyncStorageCameraRollDimensions

LinkingNetInfoPixelRatioPanResponderStyleSheet

LayoutAnimation

Poly�lls

FlexboxGeolocationNetworkTimersColors

Networking

Fetchfetch(API_URL) .then(res => res.json()) .then(data => { console.log(data); }) .catch(error => { console.warn(error); });

Async/Awaitasync function getData() { try { const res = await fetch(API_URL); const data = await res.json(); console.log(data); } catch(e) { console.warn(e) } }

Styling & Layout

StyleSheetconst styles = StyleSheet.create({ container: { backgroundColor: "#ccc", padding: 10, margin: 10, borderRadius: 3, borderWidth: 2 } });

Applying Stylesclass Container extends React.Component { render() { return ( <View style={styles.container}/> //... child components </View> ) } }

Flexboxconst styles = StyleSheet.create({ layout: { flexDirection: "row", alignItems: "center", justifyContent: "center" }, tiles: { flex: 1 } });

Custom iOSModules

// 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 AndroidModules

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 successCallback 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 ViewComponents

@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 ViewComponents

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 context return new MapView(context, Fresco.newDraweeControllerBuilder } } //Usage in javascript const RCTMap = requireNativeComponent('RCTMap', null);

React NativeTooling

DebuggingChrome Devtools

Nuclide

Redbox

Yellowbox

Pro�lingSystrace

Perf Monitor

Instruments (iOS)

JS Tooling

ES6const 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"; } }

Flowtypefunction getData(url: string, callback: Function): Object { return fetch(url) .then(res => res.json()) .then(data => callback(data)); }

TestingMocha/Jest

react-addons-test-utils

Enzyme

react-native-mock

Appium

Third PartyTooling

AppHub

CodePush

Reindex

AppBoy

RNPM

Om & Elm Native

ExponentJSNo Xcode required

Distribute apps to anyone with theapp

Exponent XDE

Exponent App

Available in the App Store

Demoexp://exp.host/@thekenwheeler/mobile-day-demo

Recommended