react native for reactjs devs
Post on 08-Jan-2017
245 Views
Preview:
TRANSCRIPT
REACT NATIVE FOR REACT DEVELOPERSBarak Cohen, Wondermall
FRONT-END IS BROKEN• Build the same app 3-6 times: iOS
(Phone/Tablet), Android (Phone/Tablet), Web (Desktop/Phone)
• Different teams build the same thing using 3 different languages, frameworks & libraries.
• Hard to maintain feature parity & consistent terminology.
• Impossible to be an expert in all technologies and “own” something in all products
STACK-CENTRIC R&D
iOS
Product Manager
Web Android
iOS Dev
iOS Dev
iOS Dev
Web Dev
Web Dev
Web Dev
Android Dev
Android Dev
Android Dev
BUSINESS-CENTRIC R&D
Feature A
Product Manager
Feature B Feature CFull-Stack
DevFull-Stack
DevFull-Stack
Dev
Full-Stack Dev
Full-Stack Dev
Full-Stack Dev
Full-Stack Dev
Full-Stack Dev
Full-Stack Dev
FULL-STACK IS HARD!• Almost all devs at Wondermall do Python,
ObjC+Swift and AngularJS
• Level of expertise vary. No one is a rock star on all 3 platforms
• We’ll never get everyone cross trained on Android, Windows Phone, Apple Watch, Apple TV, …
• If we want to remain Full Stack, we’ll have to rethink our strategy
Powered by React-Native
BASICS
REACT-NATIVE IS…• JavaScript for Application Logic
• Native UI (No WebViews)
• Flexbox Layout
• Polyfills (fetch API) & Platform APIs (Camera)
• Compatible with nearly all React and JS libs
GETTING STARTED
$ brew install node && brew install watchman
$ npm install -g react-native-cli
$ react-native init MyProject && cd MyProject
$ react-native run-ios
HELLO WORLDvar React = require('react')var { View, Text } = require('react-native')
class HelloWorldView extends React.Component { render() { return ( <View><Text>Hello World</Text></View> ) }}
React DOM React Native
React
React Canvas
React Three
iOS Android macOS Win 10 Web
REACT ECO-SYSTEM
Tizen
REACT (NATIVE+JS) BENEFITS
• “Learn once write anywhere”
• Reuse almost all non-UI code across all platforms
• Reuse most UI code between Native Platforms
• Hot-reloading JS, debug in Chrome
BENEFITS - CON’T• Can be added incrementally to an
existing app
• Over-the-wire updates w/o AppStore (AppHub)
• JS w/ ES6 is succinct and productive
• Can use previously written native code and UI
STYLE & LAYOUT
ADDING STYLEclass HelloWorldView extends React.Component { ...
render() { return ( <View style={{padding: 10}}> <Text style={{fontSize: 14, color: '#0000ff'}}> Hello World </Text> </View> ) }}
FLEXBOX LAYOUTclass HelloWorldView extends React.Component { render() { return ( <View style={{flexDirection: 'column', flex: 1}}> <View style={{flex: 1, backgroundColor: 'red'}}></View> <View style={{flex: 1, backgroundColor: 'green'}}></View> <View style={{flex: 1, backgroundColor: 'blue'}}></View> </View> ) }}
FLEXBOX LAYOUT - 2class HelloWorldView extends React.Component { render() { return ( <View style={{flexDirection: 'row', flex: 1}}> <View style={{flex: 1, backgroundColor: 'red'}}></View> <View style={{flex: 1, backgroundColor: 'green'}}></View> <View style={{flex: 1, backgroundColor: 'blue'}}></View> </View> ) }}
NATIVE APISimport React, { Component } from 'react';import { MapView } from 'react-native';
class MapMyRide extends Component { render() { return ( <MapView style={{height: 200, margin: 40}} showsUserLocation={true} /> ); }}
ROUTING
return ( <Navigator initialRoute={{ title: 'My Initial Scene', index: 0 }} renderScene={(route, navigator) => <MyScene title={route.title} onForward={ () => { navigator.push({ title: 'Scene ' + route.index + 1, index: route.index + 1, }); }} /> } /> )
BUILT-IN
REACT-NATIVE-ROUTER-FLUX
import { PageOne, PageTwo } from './Pages';
export default class App extends Component { render() { return ( <Router> <Scene key="root"> <Scene key="pageOne" component={PageOne} title="PageOne" initial={true} /> <Scene key="pageTwo" component={PageTwo} title="PageTwo" /> </Scene> </Router> ) }}
UNIVERSAL APPS
Shared - Native & WebRedux / Relay
API Client
Business Logic
Shared Native
Native Specific<TabBarIOS>,
<AndroidToolbar>
<Text>, <TextInput>, <Image>
Web<div>
Business Level Comp’
<span>
<img>
DEBUGGING & TOOLING
• Reload - Clears all JS code and resets the state
• Remote JS Debugging - Chrome / VSCode with breakpoints and Console (no network)
• Live Reload - Automatic Reload (as above)
• Hot Reloading - Change JS code without resetting the state
DEVELOPER MENU
REDUX REMOTE DEV TOOLS
PACKAGER• Built-in packager with ES6 support
• Development: local webserver serves the bundled JS
• Production:
• Use .ios.js or .android.js suffixes, Packager will include the correct file for the platform bundle
$ react-native bundle —platform ios
OTA UPDATES• Updates JS & assets without AppStore
submission
• Apple’s policy allows it for fixes & minor improvements
• Microsoft CodePush - Commercial
• AppHub - Hosted / OSS
INTEGRATION & INTERNALS
NATIVE VS. JAVASCRIPTView ControllerView ControllerView Controller Bridge
(incl. JS VM)
JavaScript FileJavaScript FileJavaScript File
RCTRootViewUIView
UIView
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions…{ NSURL *jsCodeLocation = @“http://localhost:8081/index.ios.bundle?platform=ios";
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation moduleName:@"MyComponent" initialProperties:@{} launchOptions:launchOptions];
UIViewController *rootViewController = [[UIViewController alloc] init]; rootViewController.view = rootView;
self.window.rootViewController = rootViewController; [self.window makeKeyAndVisible];}
MULTIPLE RCTROOTVIEWS
RCTRootViewUIView
UIView
RCTRootViewUIView
UIView
Bridge(incl. JS VM)
{ // AppDelegate didFinishLaunchingWithOptions self.bridge = [[RCTBridge alloc] initWithBundleURL:@"localhost..." moduleProvider:nil launchOptions:nil]
// When you want to show R/N view [[RCTRootView alloc] initWithBridge:self.bridge moduleName:"MyComponent"];
// Somewhere else [[RCTRootView alloc] initWithBridge:self.bridge moduleName:"MyOtherComponent"];
}
NATIVE MODULES• Export native functions to be called
from JS
• Export constants and enums
• Send events to JS from native
• They are singletons
// CalendarManager.h#import "RCTBridgeModule.h"
@interface CalendarManager : NSObject <RCTBridgeModule>@end
// CalendarManager.m@implementation CalendarManager
RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(addEvent:(NSString *)name location:(NSString *)location){ RCTLogInfo(@“Creating event %@ at %@", name, location);}
@end
RETURN VALUE W/ PROMISES
RCT_EXPORT_METHOD(findEvents, resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject){ NSArray *events = ... if (events) { resolve(events); } else { NSError *error = ... reject(@"no_events", @"There were no events", error); }}
import { NativeModules } from ‘react-native';
CalendarManager = NativeModules.CalendarManager;
CalendarManager.addEvent(‘Birthday Party’, …);
async function updateEvents() {try { var events = await CalendarManager.findEvents();
this.setState({ events });} catch (e) { console.error(e);}
}
updateEvents();
MISC.
PERFORMANCE TIPS• Minimize bridge messages
• Implement shouldComponentUpdate
• Direct Manipulation with setNativeProps
• Rewrite in Native
FURTHER READING• Facebook’s F8 App -
http://makeitopen.com/
• React Native Newsletter - http://reactnative.cc/
• Practice layout and Flexbox https://github.com/jondot/ReactNativeKatas
• https://github.com/jondot/awesome-react-native
STARTER KITS
• Native Starter - http://startreact.com/themes/native-starter/
• Ignite - https://github.com/infinitered/ignite
• este.js - https://github.com/este/este
3RD-PARTY COMPONENTS
• https://js.coach/react-native/
• https://react.parts/native
• nativebase.io
THANK YOU!(QUESTIONS?)
top related