Pieter De Baets - An introduction to React Native

70
REACT NATIVE

Transcript of Pieter De Baets - An introduction to React Native

Page 1: Pieter De Baets - An introduction to React Native

REACT NATIVE

Page 2: Pieter De Baets - An introduction to React Native

NATIVE DEVELOPMENT SUCKS

Page 3: Pieter De Baets - An introduction to React Native

SLOW DEVELOPMENT CYCLESLOW DEPLOYMENT CYCLE

DIFFERENT APIS TO CODE SAME THINGSSEPARATE PLATFORM TEAMS

Page 4: Pieter De Baets - An introduction to React Native

X-PLATFORM TOOLS SUCK

Page 5: Pieter De Baets - An introduction to React Native

POOR PERFORMANCENON-NATIVE FEEL

LIMITED FEATURE SUPPORTHARD TO DEBUG / POOR TOOLING

Page 6: Pieter De Baets - An introduction to React Native

COMMON TO BOTHSTATEFUL, MUTABLE UI

Page 7: Pieter De Baets - An introduction to React Native

HARD TO MANAGE COMPLEXITYHARD TO VERIFY CORRECTNESS

HARD TO MAINTAIN/RE-USE

Page 8: Pieter De Baets - An introduction to React Native

ENTER: REACT NATIVE

Page 9: Pieter De Baets - An introduction to React Native

SLOW DEVELOPMENT CYCLEINSTANT RELOAD

Page 10: Pieter De Baets - An introduction to React Native

SLOW DEPLOYMENT CYCLEDOWNLOAD UPDATES OTA WITHOUT

RESUBMISSION**APPLE SAYS IT'S OK

Page 11: Pieter De Baets - An introduction to React Native

DIFFERENT APIS TO CODE SAME THINGSCONSISTENT TOOLING & COMMON APIS FOR

EVERY PLATFORM

Page 12: Pieter De Baets - An introduction to React Native

SEPARATE PLATFORM TEAMSSHARED SKILLSET*

*UP TO 90% CODE RE-USE BETWEEN IOS AND ANDROID

Page 13: Pieter De Baets - An introduction to React Native

POOR PERFORMANCEVIRTUAL DOM

Page 14: Pieter De Baets - An introduction to React Native

NON-NATIVE FEELBACKED BY STANDARD NATIVE VIEWS

Page 15: Pieter De Baets - An introduction to React Native

LIMITED FEATURE SUPPORTEXTENSIBLE PLUGIN-BASED ARCHITECTURE

Page 16: Pieter De Baets - An introduction to React Native

HARD TO DEBUG / POOR TOOLINGBREAKPOINTS AND SINGLE-STEP DEBUGGING

WITH BROWSER-BASED DEV TOOLS

Page 17: Pieter De Baets - An introduction to React Native

STATEFUL, MUTABLE UIIMMUTABLE VIEWS, PURE RENDER FUNCTIONS, ONE-WAY DATA FLOW

Page 18: Pieter De Baets - An introduction to React Native

REACT NATIVE ISFUNCTIONAL UIVIRTUAL DOM

FLEXBOX LAYOUTJAVASCRIPT FRONT-END

NATIVE BACK-END

Page 19: Pieter De Baets - An introduction to React Native

FUNCTIONAL UIDEFINING STATES, NOT TRANSITIONS

Page 20: Pieter De Baets - An introduction to React Native

IMPERATIVE UI: DEFINE TRANSITIONSFUNCTIONAL UI: DEFINE STATES

Page 21: Pieter De Baets - An introduction to React Native

IMPERATIVE UI: DEFINE TRANSITIONS

Page 22: Pieter De Baets - An introduction to React Native

IMPERATIVE UI: DEFINE TRANSITIONS

Page 23: Pieter De Baets - An introduction to React Native

IMPERATIVE UI: DEFINE TRANSITIONS

Page 24: Pieter De Baets - An introduction to React Native

IMPERATIVE UI: DEFINE TRANSITIONS

Page 25: Pieter De Baets - An introduction to React Native

IMPERATIVE UI: DEFINE TRANSITIONS

Page 26: Pieter De Baets - An introduction to React Native

3 STATES

9 TRANSITIONS

Page 27: Pieter De Baets - An introduction to React Native

O(N2)

Page 28: Pieter De Baets - An introduction to React Native

if (count > 99) { // branch 1 if (!hasFire()) { // branch 2 addFire(); }} else { if (hasFire()) { // branch 3 removeFire(); }}if (count === 0) { // branch 4 if (hasBadge()) { // branch 5 removeBadge(); } return;}if (!hasBadge()) { // branch 6 addBadge();}var countText = count > 99 ? '99+' : count.toString(); // branch 7getBadge().setText(countText);

Page 29: Pieter De Baets - An introduction to React Native

FUNCTIONAL UI: DEFINE STATES

if (count === 0) { // state 1 return <Bell/>;}

Page 30: Pieter De Baets - An introduction to React Native

FUNCTIONAL UI: DEFINE STATES

if (count === 0) { // state 1 return <Bell/>;} else if(count <= 99) { // state 2 return ( <Bell> <Badge count={count} /> </Bell> );}

Page 31: Pieter De Baets - An introduction to React Native

FUNCTIONAL UI: DEFINE STATES

if (count === 0) { // state 1 return <Bell/>;} else if(count <= 99) { // state 2 return ( <Bell> <Badge count={count} /> </Bell> );} else { // state 3 return ( <Bell style={styles.onFire}> <Badge count=“99+” /> </Bell> );}

Page 32: Pieter De Baets - An introduction to React Native

VIEW IS RECREATED EACH TIMEBUT ISN'T THAT SLOW?

Page 33: Pieter De Baets - An introduction to React Native

VIRTUAL DOM**DOCUMENT OBJECT MODEL

(AKA VIEW HIERARCHY)

Page 34: Pieter De Baets - An introduction to React Native
Page 35: Pieter De Baets - An introduction to React Native

REACT CALCULATES CHANGESET ON THE JS SIDE

Page 36: Pieter De Baets - An introduction to React Native

AUTORESIZING VS AUTOLAYOUT

Page 37: Pieter De Baets - An introduction to React Native

AUTORESIZING VS AUTOLAYOUTFLEXBOX LAYOUT

Page 38: Pieter De Baets - An introduction to React Native

FLEXBOX APIEXPLICT AND INFERRED POSITIONING

CONTAINERS SPECIFY LAYOUT FOR CHILDRENDIVIDES CONTENT INTO ROWS & COLUMNS

BASED ON CSS STANDARDS

Page 39: Pieter De Baets - An introduction to React Native

FLEX DIRECTION

flexDirection: 'row' | 'column' (default)

This defines the main axis along which subviews are stacked.

Page 40: Pieter De Baets - An introduction to React Native

JUSTIFY CONTENT

justifyContent: 'flex-start' (default) | 'center' | 'flex-end' | 'space-between' | 'space-around'

This defines how views align along the main axis.

Page 41: Pieter De Baets - An introduction to React Native

ALIGN ITEMS

alignItems: 'flex-start' (default) | 'center' | 'flex-end'

This defines how views align along the cross axis.

Page 42: Pieter De Baets - An introduction to React Native

FLEX

flex: (number)

A flex value > 0 indicates that a view should scale to fill its container. Flex values > 1 control the relative size of views inside their parent.

Page 43: Pieter De Baets - An introduction to React Native

FLEX WRAP

flexWrap: 'nowrap' (default) | 'wrap'

With the flexWrap style, subviews that overflow the bounds of their container can be set to automatically wrap onto the next line.

Page 44: Pieter De Baets - An introduction to React Native

JAVASCRIPT FRONT-END

Page 45: Pieter De Baets - An introduction to React Native

JAVASCRIPT!?

Page 46: Pieter De Baets - An introduction to React Native

WHY JAVASCRIPT?ALREADY SUPPORTED X-PLATFORM

REACT ALREADY USES ITONLY OPTION FOR OTA UPDATES

Page 47: Pieter De Baets - An introduction to React Native

3.3.2 An Application may not download or install executable code.Interpreted code may only be used in an Application if all scripts,

code and interpreters are packaged in the Application and notdownloaded. The only exception to the foregoing is scripts andcode downloaded and run by Apple's built-in WebKit framework,provided that such scripts and code do not change the primary

purpose of the Application by providing features or functionalitythat are inconsistent with the intended and advertised purpose of

the Application as submitted to the App Store.

Page 48: Pieter De Baets - An introduction to React Native

BUT... JAVASCRIPT SUCKS

Page 49: Pieter De Baets - An introduction to React Native

WEAKLY TYPEDGARBAGE COLLECTED

INTERPRETED

Page 50: Pieter De Baets - An introduction to React Native

IF ONLY JAVASCRIPT

function foo(fn, x) { return fn(x);}

Page 51: Pieter De Baets - An introduction to React Native

IF ONLY JAVASCRIPT

function foo(fn, x) { return fn(x);}

WAS MORE LIKE SWIFT

function foo<X, Y>(fn: F<X, Y>, x: X): Y { return fn(x);}

Page 52: Pieter De Baets - An introduction to React Native

FLOWSTATIC ANALYSIS, STRONG TYPING AND

TYPE INFERENCE FOR JAVASCRIPT

Page 53: Pieter De Baets - An introduction to React Native

TYPE ALIASES TRUE CLASSES MAYBE TYPES UNIONS ENUMS GENERICS TUPLES MIXINS

ARROW FUNCTIONS DESTRUCTURING

Page 54: Pieter De Baets - An introduction to React Native

GARBAGE COLLECTIONINTERPRETED CODE

Page 55: Pieter De Baets - An introduction to React Native

GARBAGE COLLECTIONINTERPRETED CODE

ASYNC EXECUTION**JS RUNS ON A DEDICATED THREAD - DOESN'T BLOCK UI

Page 56: Pieter De Baets - An introduction to React Native

EXAMPLEvar React = require('react-native');var { AppRegistry, StyleSheet, Text, View } = React;

class HelloWorld extends React.Component { render() { return ( React.createElement(View, {style: styles.container}, React.createElement(Text, null, "Hello World!") ) ); },});

var styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', }});

AppRegistry.registerComponent('HelloWorld', () => HelloWorld);

Page 57: Pieter De Baets - An introduction to React Native

JSX (JAVASCRIPT + XML)var React = require('react-native');var { AppRegistry, StyleSheet, Text, View } = React;

class HelloWorld extends React.Component { render() { return ( <View style={styles.container}> <Text>Hello World</Text> </View> ); },});

var styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', }});

AppRegistry.registerComponent('HelloWorld', () => HelloWorld);

Page 58: Pieter De Baets - An introduction to React Native

NATIVE BACK-END

Page 59: Pieter De Baets - An introduction to React Native

INTEGRATIONNSURL *src = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle"];NSString *moduleName = @"MyApp";

// Option 1

RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:src moduleName:moduleName launchOptions:nil];

// Option 2

RCTBridge *bridge = [[RCTBridge alloc] initWithBundleURL:src moduleProvider:nil launchOptions:nil];

RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:moduleName];

Page 60: Pieter De Baets - An introduction to React Native

PLUGIN ARCHITECTUREBRIDGE MODULESVIEW MANAGERS

(MORE IN FUTURE)

Page 61: Pieter De Baets - An introduction to React Native

BRIDGE MODULES// CalendarManager.m

@interface CalendarManager : NSObject <RCTBridgeModule>@end

@implementation CalendarManager

RCT_EXPORT_MODULE()

RCT_EXPORT_METHOD(addEvent:(NSString *)name location:(NSString *)location){ RCTLogInfo(@"Pretending to create an event %@ at %@", name, location);}

@end

// CalendarManager.js

var CalendarManager = require('NativeModules').CalendarManager;CalendarManager.addEvent('Birthday Party', '4 Privet Drive, Surrey');

Page 62: Pieter De Baets - An introduction to React Native

TYPE CONVERSION// CalendarManager.m

@implementation CalendarManager

RCT_EXPORT_MODULE()

RCT_EXPORT_METHOD(addEvent:(NSString *)name date:(NSDate *)date){ RCTLogInfo(@"Pretending to create an event %@ on %@", name, date);}

@end

// CalendarManager.js

CalendarManager.addEvent( 'Birthday Party', date.toTime() // returns time in seconds since unix epoch);

Page 63: Pieter De Baets - An introduction to React Native

CALLBACKS// CalendarManager.m

@implementation CalendarManager...

RCT_EXPORT_METHOD(findEvents:(RCTResponseSenderBlock)callback){ NSArray *events = ... callback(@[[NSNull null], events]);}

@end

// CalendarManager.js

CalendarManager.findEvents((error, events) => { if (error) { console.error(error); } else { // do something with events }})

Page 64: Pieter De Baets - An introduction to React Native

VIEW MANAGERS// MapManager.m

@interface MapManager : RCTViewManager <MKMapViewDelegate>@end

@implementation MapManager

RCT_EXPORT_MODULE()

- (UIView *)view{ return [[MKMapView alloc] init];}

@end

// MapView.js

var React = require('react-native');var { requireNativeComponent } = React;module.exports = requireNativeComponent('Map', null);

Page 65: Pieter De Baets - An introduction to React Native

PROPERTY BINDING// MapManager.m

@implementation MapManager...RCT_EXPORT_VIEW_PROPERTY(pitchEnabled, BOOL)

@end

// MapView.js

var React = require('react-native');var { requireNativeComponent } = React;

class MapView extends React.Component { render() { return <Map {...this.props} />; }}

MapView.propTypes = { pitchEnabled: React.PropTypes.bool,};

var Map = requireNativeComponent('Map', MapView);module.exports = MapView;

Page 66: Pieter De Baets - An introduction to React Native

EVENTS// MapManager.m

@implementation MapManager

RCT_EXPORT_MODULE()

- (UIView *)view{ MKMapView *map = [[MKMapView alloc] init]; map.delegate = self; return map;}

#pragma mark MKMapViewDelegate

- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated{ MKCoordinateRegion region = mapView.region; NSDictionary *event = @{ @"lat": @(region.center.latitude), @"long": @(region.center.longitude) }; [self.bridge.eventDispatcher sendInputEventWithName:@"topChange" body:event];}

@end

Page 67: Pieter De Baets - An introduction to React Native

EVENTS// MapView.js

class MapView extends React.Component { constructor() { this._onChange = this._onChange.bind(this); }

_onChange(event: Event) { if (!this.props.onRegionChange) { return; } this.props.onRegionChange(event.nativeEvent.region); }

render() { return <Map {...this.props} onChange={this._onChange} />; }}

MapView.propTypes = { pitchEnabled: React.PropTypes.bool, onRegionChange: React.PropTypes.func,};

Page 68: Pieter De Baets - An introduction to React Native

WHAT ABOUT SWIFT?// CalendarManagerBridge.m

#import "RCTBridgeModule.h"

@interface RCT_EXTERN_MODULE(CalendarManager, NSObject)

RCT_EXTERN_METHOD(addEvent:(NSString *)name location:(NSString *)location date:(NSDate *)date)

@end

// CalendarManager.swift

@objc(CalendarManager)class CalendarManager: NSObject {

@objc func addEvent(name: String, location: String, date: NSDate) -> Void { // Date is ready to use! }}

Page 69: Pieter De Baets - An introduction to React Native

LINKS

React Native on Githubhttps://facebook.github.io/react-native/

Colin Eberhardt's RayWenderlich.com Tutorialhttp://tinyurl.com/rw-react-tutorial

Christopher Chedeau’s ReactJS Conf Keynotehttps://www.youtube.com/watch?v=7rDsRXj9-cU

Page 70: Pieter De Baets - An introduction to React Native

Q&A