React Native Developing an app similar to Uber in JavaScript
Caio Ariede Full Stack Developer at Parasail.com 2/16/2017 github.com/caioariede
Topics ● ECMAScript 6 (es6) ● React ● React Native ● Develop an app similar to Uber
ES 6 2015 "Harmony"
ES6: Modules // lib/math.js export function sum (x, y) { return x + y } export var pi = 3.141593 // someApp.js import * as math from "lib/math" console.log("2π = " + math.sum(math.pi, math.pi))
ES6: Classes class Circle extends Shape { constructor (id, x, y, radius) { super(id, x, y) this.radius = radius } }
React
React: JSX const element = ( <h1 className="greeting"> Hello, world! </h1> )
React: Components class Welcome extends React.Component { render() { return <h1>Welcome, {this.props.name}</h1>; } } // <Welcome name="Fulano" />
React: State class Counter extends React.Component { state = {counter: 0} onClick() { this.setState({counter: this.state.counter+1}) } render() { return <div> <span>{this.state.counter}</span> <button onClick={this.onClick}>add</button> </div> } }
React: VirtualDOM Component VirtualDOM DOM (Browser) render
React Native
React Native: Who uses?
React Native: Features ● Native apps (native UI components) ● No need to recompile every time ● Reusable code for iOS and Android (80%) ● Communication with native functions ○ Objective-C, Java
Fonte: https://speakerdeck.com/frantic/react-native-under-the-hood
Idea: App similar to Uber ● Login with Facebook ● Geolocation (passenger) ● Real-time updates (drivers) ● Trace/display route ● Nearest driver Using only JavaScript
Dependencies
Getting Started ● npm install -g react-native-cli ● react-native init UberProject ● react-native run-ios
Project dependencies ● firebase: backend/database ● react-native-fbsdk: login with facebook ● react-native-maps: native map components ● geofire: location queries ● mapbox: calculate routes
Firebase: what's? ● Backend as a service ● Real-time database ● Handles authentication ○ oAuth, Facebook, Google, etc.
Firebase: authentication OAuth token Check token
Login onClick() { LoginManager.logInWithReadPermissions(['public_profile']).then(result => { if (!result.isCancelled) { } else { console.log('login: user cancelled') } }) } onClick() { LoginManager.logInWithReadPermissions(['public_profile']).then(result => { if (!result.isCancelled) { AccessToken.getCurrentAccessToken().then(tokenResult => { return auth.signInWithCredential( facebook.credential(tokenResult.accessToken)) }).catch(err => console.log('login error: ' + err)) } else { console.log('login: user cancelled') } }) }
Idea: App similar to Uber ● Login with Facebook √ ● Geolocation (passenger) ● Real-time updates (drivers) ● Trace/display route ● Nearest driver
Map class Map extends Component { state = { passengerPosition: {latitude: 0, longitude: 0}, } render() { return ( <MapView> <Marker coordinate={this.state.passengerPosition} /> </MapView> ) } }
watchPassenger() { const positionOptions = { enableHighAccuracy: true, } navigator.geolocation.watchPosition(pos => { this.updatePassengerPosition({latitude: pos.latitude, longitude: pos.longitude}) }, positionOptions) } updatePassengerPosition(passengerPosition) { this.setState({passengerPosition}) } Geolocation
Saving location to Firebase updatePassengerPosition(passengerPosition) { this.setState({passengerPosition}) const user = firebase.database().ref('users/' + this.userId) user.update({passengerPosition}) }
Idea: App similar to Uber ● Login with Facebook √ ● Geolocation (passenger) √ ● Real-time updates (drivers) ● Trace/display route ● Nearest driver
Real-time updates of drivers watchDrivers() { firebase.database().ref('drivers').on('child_changed', data => { let drivers = this.state.drivers drivers[driver.id] = {id: data.key, position} this.setState({drivers}) }) }
Displaying drivers on map renderDrivers() { return this.state.drivers.map(driver => ( <Marker key={driver.id} coordinate={driver.position} image={carIcon} /> )) }
Idea: App similar to Uber ● Login with Facebook √ ● Geolocation (passenger) √ ● Real-time updates (drivers) √ ● Trace/display route ● Nearest driver
Destination class SetDestination extends MapMixin { constructor(props) { this.state.destinationPosition = randomPosition( props.passengerPosition, 500) // 500 meters } renderDestinationPosition() { return <Marker draggable image={markerIcon} coordinate={this.state.destinationPosition} /> } }
Trace route calculateRoute() { const mode = 'driving' const origin = buildLngLat(this.state.pickupPosition) const destination = buildLngLat(this.state.destinationPosition) const accessToken = this.mapBoxAccessToken const url = buildMapBoxUrl(mode, origin, destination, accessToken) fetch(url).then(response => response.json()).then(json => { this.setState({route: getCoordinates(json)}) }).catch(e => { console.warn(e) }) }
Display route renderRoute() { return ( <MapView.Polyline strokeWidth={4} coordinates={[this.state.passengerPosition, ...this.state.route, this.state.destinationPosition]} /> ) }
Idea: App similar to Uber ● Login with Facebook √ ● Geolocation (passenger) √ ● Real-time updates (drivers) √ ● Trace/display route √ ● Nearest driver
GeoFire geofire key1: 37,-122 key2: lat, lng key3: lat, lng geoFire.set("key1", [37, -122]) listener geoquery lat, lng raio geoquery lat, lng raio Notify current geoqueries
Nearest driver let radius = 0.1 // 100m let currentLocation = [ passengerPosition.latitude, passengerPosition.longitude, ] let geoQuery = this.geoFire.query({center: currentLocation, radius}) let driversFound = [] geoQuery.on('key_entered', (key, location, distance) => { driversFound.push({key, location, distance}) }) watchDriversFound()
Nearest driver watchDriversFound() { if (driversFound.length === 0) { geoQuery.updateCriteria({radius: radius + 0.1}) } else { let minDistance = -1, nearestDriver = null driversFound.forEach(driver => { if (driver.distance < minDistance || minDistance === -1) minDistance = driver.distance, nearestDriver = driver }) this.setState({nearestDriver: driver}) } }
Idea: App similar to Uber ● Login with Facebook √ ● Geolocation (passenger) √ ● Real-time updates (drivers) √ ● Trace/display route √ ● Nearest driver √
Questions? caioariede on github and twitter

React Native: Developing an app similar to Uber in JavaScript

  • 1.
    React Native Developing anapp similar to Uber in JavaScript
  • 2.
    Caio Ariede Full StackDeveloper at Parasail.com 2/16/2017 github.com/caioariede
  • 3.
    Topics ● ECMAScript 6(es6) ● React ● React Native ● Develop an app similar to Uber
  • 4.
  • 5.
    ES6: Modules // lib/math.js exportfunction sum (x, y) { return x + y } export var pi = 3.141593 // someApp.js import * as math from "lib/math" console.log("2π = " + math.sum(math.pi, math.pi))
  • 6.
    ES6: Classes class Circleextends Shape { constructor (id, x, y, radius) { super(id, x, y) this.radius = radius } }
  • 7.
  • 8.
    React: JSX const element= ( <h1 className="greeting"> Hello, world! </h1> )
  • 9.
    React: Components class Welcomeextends React.Component { render() { return <h1>Welcome, {this.props.name}</h1>; } } // <Welcome name="Fulano" />
  • 10.
    React: State class Counterextends React.Component { state = {counter: 0} onClick() { this.setState({counter: this.state.counter+1}) } render() { return <div> <span>{this.state.counter}</span> <button onClick={this.onClick}>add</button> </div> } }
  • 11.
  • 12.
  • 13.
  • 14.
    React Native: Features ●Native apps (native UI components) ● No need to recompile every time ● Reusable code for iOS and Android (80%) ● Communication with native functions ○ Objective-C, Java
  • 15.
  • 17.
    Idea: App similarto Uber ● Login with Facebook ● Geolocation (passenger) ● Real-time updates (drivers) ● Trace/display route ● Nearest driver Using only JavaScript
  • 18.
  • 19.
    Getting Started ● npminstall -g react-native-cli ● react-native init UberProject ● react-native run-ios
  • 20.
    Project dependencies ● firebase:backend/database ● react-native-fbsdk: login with facebook ● react-native-maps: native map components ● geofire: location queries ● mapbox: calculate routes
  • 22.
    Firebase: what's? ● Backendas a service ● Real-time database ● Handles authentication ○ oAuth, Facebook, Google, etc.
  • 23.
  • 24.
    Login onClick() { LoginManager.logInWithReadPermissions(['public_profile']).then(result =>{ if (!result.isCancelled) { } else { console.log('login: user cancelled') } }) } onClick() { LoginManager.logInWithReadPermissions(['public_profile']).then(result => { if (!result.isCancelled) { AccessToken.getCurrentAccessToken().then(tokenResult => { return auth.signInWithCredential( facebook.credential(tokenResult.accessToken)) }).catch(err => console.log('login error: ' + err)) } else { console.log('login: user cancelled') } }) }
  • 25.
    Idea: App similarto Uber ● Login with Facebook √ ● Geolocation (passenger) ● Real-time updates (drivers) ● Trace/display route ● Nearest driver
  • 26.
    Map class Map extendsComponent { state = { passengerPosition: {latitude: 0, longitude: 0}, } render() { return ( <MapView> <Marker coordinate={this.state.passengerPosition} /> </MapView> ) } }
  • 27.
    watchPassenger() { const positionOptions= { enableHighAccuracy: true, } navigator.geolocation.watchPosition(pos => { this.updatePassengerPosition({latitude: pos.latitude, longitude: pos.longitude}) }, positionOptions) } updatePassengerPosition(passengerPosition) { this.setState({passengerPosition}) } Geolocation
  • 28.
    Saving location toFirebase updatePassengerPosition(passengerPosition) { this.setState({passengerPosition}) const user = firebase.database().ref('users/' + this.userId) user.update({passengerPosition}) }
  • 29.
    Idea: App similarto Uber ● Login with Facebook √ ● Geolocation (passenger) √ ● Real-time updates (drivers) ● Trace/display route ● Nearest driver
  • 30.
    Real-time updates ofdrivers watchDrivers() { firebase.database().ref('drivers').on('child_changed', data => { let drivers = this.state.drivers drivers[driver.id] = {id: data.key, position} this.setState({drivers}) }) }
  • 31.
    Displaying drivers onmap renderDrivers() { return this.state.drivers.map(driver => ( <Marker key={driver.id} coordinate={driver.position} image={carIcon} /> )) }
  • 32.
    Idea: App similarto Uber ● Login with Facebook √ ● Geolocation (passenger) √ ● Real-time updates (drivers) √ ● Trace/display route ● Nearest driver
  • 33.
    Destination class SetDestination extendsMapMixin { constructor(props) { this.state.destinationPosition = randomPosition( props.passengerPosition, 500) // 500 meters } renderDestinationPosition() { return <Marker draggable image={markerIcon} coordinate={this.state.destinationPosition} /> } }
  • 34.
    Trace route calculateRoute() { constmode = 'driving' const origin = buildLngLat(this.state.pickupPosition) const destination = buildLngLat(this.state.destinationPosition) const accessToken = this.mapBoxAccessToken const url = buildMapBoxUrl(mode, origin, destination, accessToken) fetch(url).then(response => response.json()).then(json => { this.setState({route: getCoordinates(json)}) }).catch(e => { console.warn(e) }) }
  • 35.
    Display route renderRoute() { return( <MapView.Polyline strokeWidth={4} coordinates={[this.state.passengerPosition, ...this.state.route, this.state.destinationPosition]} /> ) }
  • 36.
    Idea: App similarto Uber ● Login with Facebook √ ● Geolocation (passenger) √ ● Real-time updates (drivers) √ ● Trace/display route √ ● Nearest driver
  • 37.
    GeoFire geofire key1: 37,-122 key2: lat,lng key3: lat, lng geoFire.set("key1", [37, -122]) listener geoquery lat, lng raio geoquery lat, lng raio Notify current geoqueries
  • 38.
    Nearest driver let radius= 0.1 // 100m let currentLocation = [ passengerPosition.latitude, passengerPosition.longitude, ] let geoQuery = this.geoFire.query({center: currentLocation, radius}) let driversFound = [] geoQuery.on('key_entered', (key, location, distance) => { driversFound.push({key, location, distance}) }) watchDriversFound()
  • 39.
    Nearest driver watchDriversFound() { if(driversFound.length === 0) { geoQuery.updateCriteria({radius: radius + 0.1}) } else { let minDistance = -1, nearestDriver = null driversFound.forEach(driver => { if (driver.distance < minDistance || minDistance === -1) minDistance = driver.distance, nearestDriver = driver }) this.setState({nearestDriver: driver}) } }
  • 40.
    Idea: App similarto Uber ● Login with Facebook √ ● Geolocation (passenger) √ ● Real-time updates (drivers) √ ● Trace/display route √ ● Nearest driver √
  • 41.