Slide 1

Slide 1 text

Flutter or React Native a cross-platform dilemma Marco Gomiero

Slide 2

Slide 2 text

WHO I AM Mobile Engineer @ Uniwhere MARCO GOMIERO COMPUTER ENGINEER Co-Leader @ GDG Venezia

Slide 3

Slide 3 text

LET’S GET IN TOUCH! twitter.com/marcoGomier MARCO GOMIERO COMPUTER ENGINEER github.com/prof18 marco.gomiero.93[at]gmail[dot]com marcogomiero.com

Slide 4

Slide 4 text

Disclaimer

Slide 5

Slide 5 text

Background

Slide 6

Slide 6 text

Background Flutter React Native

Slide 7

Slide 7 text

Background Flutter

Slide 8

Slide 8 text

Background Flutter

Slide 9

Slide 9 text

Background Flutter

Slide 10

Slide 10 text

Background Flutter

Slide 11

Slide 11 text

Background Flutter

Slide 12

Slide 12 text

Background Flutter

Slide 13

Slide 13 text

Background Flutter

Slide 14

Slide 14 text

Agenda • History • Language • UI • Under the hood • Example • Conclusions

Slide 15

Slide 15 text

History JANUARY 2015 First public preview MAY 2015 Open sourced and launched officially SUMMER 2013 First version developed during an internal hackathon 2013 2015 2015 React Native

Slide 16

Slide 16 text

History JANUARY 2015 First public preview MAY 2015 Open sourced and launched officially SUMMER 2013 First version developed during an internal hackathon 2013 2015 2015 Flutter React Native MAY 2017 Alpha Release DECEMBER 2018 First 1.0 version APRIL 2015 Unveiled at Dart Dev Summit 2015 2018 2017

Slide 17

Slide 17 text

Trends React Native Flutter UPDATE Last update: September 2019

Slide 18

Slide 18 text

Trends Last update: September 2019

Slide 19

Slide 19 text

LANGUAGE

Slide 20

Slide 20 text

Survey

Slide 21

Slide 21 text

React Native • Javascript • ☠ for Object Oriented Devs: • Type Conversion • Sometimes silently fails • Prototype based inheritance • Ecosystem Confusion

Slide 22

Slide 22 text

No content

Slide 23

Slide 23 text

Flutter • Dart, invented by Google in 2011 • Object Oriented friendly • e.g strongly typed but type can be inferred • Flat learning curve for OO devs • Mobile -> compiles to ARM and x86 code • Web -> transpiles to Javascript

Slide 24

Slide 24 text

!crusade It’s not a language crusade, just my experience

Slide 25

Slide 25 text

UI

Slide 26

Slide 26 text

No content

Slide 27

Slide 27 text

// React Native import React from "react"; import { StyleSheet, Text, View } from "react-native"; export default class App extends React.Component { render() { return ( Hello world! ); } } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: "#fff", alignItems: "center", justifyContent: "center" } });

Slide 28

Slide 28 text

// React Native import React from "react"; import { StyleSheet, Text, View } from "react-native"; export default class App extends React.Component { render() { return ( Hello world! ); } } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: "#fff", alignItems: "center", justifyContent: "center" } }); // Flutter import 'package:flutter/material.dart'; void main() { runApp( Center( child: Text( 'Hello, world!', textDirection: TextDirection.ltr, ), ), ); }

Slide 29

Slide 29 text

// React Native import React from "react"; import { StyleSheet, Text, View } from "react-native"; export default class App extends React.Component { render() { return ( Hello world! ); } } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: "#fff", alignItems: "center", justifyContent: "center" } }); // Flutter import 'package:flutter/material.dart'; void main() { runApp( Center( child: Text( 'Hello, world!', textDirection: TextDirection.ltr, ), ), ); }

Slide 30

Slide 30 text

// React Native import React from "react"; import { StyleSheet, Text, View } from "react-native"; export default class App extends React.Component { render() { return ( Hello world! ); } } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: "#fff", alignItems: "center", justifyContent: "center" } });

Slide 31

Slide 31 text

// React Native import React from "react"; import { StyleSheet, Text, View } from "react-native"; export default class App extends React.Component { render() { return ( Hello world! ); } } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: "#fff", alignItems: "center", justifyContent: "center" } });

Slide 32

Slide 32 text

// React Native import React from "react"; import { StyleSheet, Text, View } from "react-native"; export default class App extends React.Component { render() { return ( Hello world! ); } } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: "#fff", alignItems: "center", justifyContent: "center" } });

Slide 33

Slide 33 text

// React Native import React from "react"; import { StyleSheet, Text, View } from "react-native"; export default class App extends React.Component { render() { return ( Hello world! ); } } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: "#fff", alignItems: "center", justifyContent: "center" } });

Slide 34

Slide 34 text

// React Native import React from "react"; import { StyleSheet, Text, View } from "react-native"; export default class App extends React.Component { render() { return ( Hello world! ); } } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: "#fff", alignItems: "center", justifyContent: "center" } }); Components • Basic UI building blocks • Fit together to form a custom component • Domain specific language called JSX • Customisable with CSS • Or better “usually match how CSS works on the web”

Slide 35

Slide 35 text

https://facebook.github.io/react-native/docs/components-and-apis.html

Slide 36

Slide 36 text

// React Native import React from "react"; import { StyleSheet, Text, View } from "react-native"; export default class App extends React.Component { render() { return ( Hello world! ); } } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: "#fff", alignItems: "center", justifyContent: "center" } }); // Flutter import 'package:flutter/material.dart'; void main() { runApp( Center( child: Text( 'Hello, world!', textDirection: TextDirection.ltr, ), ), ); }

Slide 37

Slide 37 text

// Flutter import 'package:flutter/material.dart'; void main() { runApp( Center( child: Text( 'Hello, world!', textDirection: TextDirection.ltr, ), ), ); }

Slide 38

Slide 38 text

// Flutter import 'package:flutter/material.dart'; void main() { runApp( Center( child: Text( 'Hello, world!', textDirection: TextDirection.ltr, ), ), ); }

Slide 39

Slide 39 text

// Flutter import 'package:flutter/material.dart'; void main() { runApp( Center( child: Text( 'Hello, world!', textDirection: TextDirection.ltr, ), ), ); }

Slide 40

Slide 40 text

// Flutter import 'package:flutter/material.dart'; void main() { runApp( Center( child: Text( 'Hello, world!', textDirection: TextDirection.ltr, ), ), ); } • Basic UI building blocks • Takes inspiration from RN • Everything is a Widget Widgets

Slide 41

Slide 41 text

Structural Element (Button, Menu …)

Slide 42

Slide 42 text

Stylistic Element (Font, Color Scheme ..)

Slide 43

Slide 43 text

Aspect of Layout (Padding, Align ..)

Slide 44

Slide 44 text

https://flutter.io/docs/development/ui/widgets

Slide 45

Slide 45 text

Components vs Widgets: Summary • React Native: jumps from Javascript to JSX • Flutter: remains in the Dart context • Possibility of UI modularisation

Slide 46

Slide 46 text

Components vs Widgets: Summary • React Native: jumps from Javascript to JSX • Flutter: remains in the Dart context • Possibility of UI modularisation

Slide 47

Slide 47 text

State Management • You should do it! • Separation of presentation logic from business logic • Data sync from different components/widget … • React Native: “Naive method”, Redux, .. • Flutter: “Naive method”, Scoped Model, BLoC, Redux, ..

Slide 48

Slide 48 text

State Management - Flutter • https://www.youtube.com/watch?v=PLHln7wHgPE • https://www.youtube.com/watch?v=RS36gBEp8OI • https://www.youtube.com/watch?v=d_m5csmrf7I • http://fluttersamples.com/

Slide 49

Slide 49 text

Declarative UI • Imperative style: retrieve an instance from the view owner and update it based on the new state • Describe the current UI state and the framework manages state changes

Slide 50

Slide 50 text

No content

Slide 51

Slide 51 text

Jetpack Compose https://developer.android.com/jetpack/compose

Slide 52

Slide 52 text

Jetpack Compose • Kotlin based • Composable function that transform application data to UI hierarchy import androidx.compose.* import androidx.ui.core.* @Composable fun Greeting(name: String) { Text ("Hello $name!") }

Slide 53

Slide 53 text

No content

Slide 54

Slide 54 text

https://developer.apple.com/xcode/swiftui/

Slide 55

Slide 55 text

https://developer.apple.com/xcode/swiftui/

Slide 56

Slide 56 text

UNDER THE HOOD

Slide 57

Slide 57 text

React Native • Core: an infrastructure, aka “Bridge” built at runtime • It lets native code call JS and viceversa • Your code run inside a JS Virtual Machine: JavaScriptCore • Event driven

Slide 58

Slide 58 text

• Event driven Event Serialized Payload Process Event Process Command Serialized Response Call native methods App opening [1, 1, [‘My App’, {}]] [[2, 3, [2, ‘View’, {…}]], [2, 3, [3, ‘View’, {…}]]] val view = View() val view = TextView() Render new Views

Slide 59

Slide 59 text

• Calls passed between JS to Native in a “batched asynchronous way” • quequed in the MessageQueue -> flushed every 5 ms by default • Event driven

Slide 60

Slide 60 text

New RN Architecture • React Native team is working on a new architecture: Fabric • High priority UI updates synchronously • No more bridge and serialisation • JSI (JavaScript Interface) between JS and Native Code https://www.youtube.com/watch?v=UcqRXTriUVI

Slide 61

Slide 61 text

Flutter • Dart code compiled into native, ARM and x86 libraries • Widgets are managed and rendered using a C++ engine Framework (Dart) Engine (C++) Skia Dart Text Material Cupertino Widgets Rendering Animation Painting Gestures Foundation

Slide 62

Slide 62 text

Flutter • Dart code compiled into native, ARM and x86 libraries • Widgets are managed and rendered using a C++ engine • All elements are rendered with Skia, a 2-d graphics library • Pro: take advantage of the GPU • Cons: app size is larger

Slide 63

Slide 63 text

Recap • Components translated to native • Use Native components • Delay due to Bridge initialisation and runtime translation • Widget independent of the OS • No translation time needed • Include its own widgets

Slide 64

Slide 64 text

Common Interesting Features: • Hot reload without losing state

Slide 65

Slide 65 text

• Hot reload without losing state • Build on top of Hot Module Replacement by Webpack • HMR runtime included in the app that receives new module and replace it

Slide 66

Slide 66 text

• Hot reload without losing state • State is maintained during builds • Thanks to a mix of Ahead- of-time (AOT) and Just-In- Time (JIT) compilation

Slide 67

Slide 67 text

Common Interesting Features: • Hot reload without losing state • Update only components/widget that have changed

Slide 68

Slide 68 text

• Update only components/widget that have changed • Virtual DOM as representation of the UI OK! { type: 'button', props: { className: 'button button-blue', children: { type: 'b', props: { children: 'OK!' } } } }

Slide 69

Slide 69 text

• Update only components/widget that have changed • Virtual DOM as representation of the UI • Diff comparison using reconciliation • O(n) heuristic algorithm thanks to two assumption: • Two elements of different types will produce different trees. • The developer can hint at which child elements may be stable across different renders with a key prop.

Slide 70

Slide 70 text

• Update only components/widget that have changed • Element Tree as representation of the UI

Slide 71

Slide 71 text

• Update only components/widget that have changed • Element Tree as representation of the UI • After an user input or other stimuli a widget must be redrawn • Not a tree-diffing algorithm • For each element, the child list is examined independently (O(n) algorithm)

Slide 72

Slide 72 text

Common Interesting Features: • Hot reload without losing state • Update only components/widget that have changed • “Frankestein” App

Slide 73

Slide 73 text

• “Frankestein” App • Add new React Native based features, screens, views, etc. in an existing application • Useful for “evolving features” • A view in the native app is a container for the RN component

Slide 74

Slide 74 text

• “Frankestein” App

Slide 75

Slide 75 text

• “Frankestein” App

Slide 76

Slide 76 text

EXAMPLE

Slide 77

Slide 77 text

render() { return ( ( { ... this.setState({ ... }) }} /> : { this.setState({ ... }) ... }} />} /> )} extraData={this.state} keyExtractor={item => item.label} /> ); } const styles = StyleSheet.create({ container: { borderRadius: 5, backgroundColor: "#F3F3F3", marginHorizontal: 10, marginVertical: 5, }, icon: { marginEnd: 10, padding: 20 }, });

Slide 78

Slide 78 text

render() { return ( ( { ... this.setState({ ... }) }} /> : {

Slide 79

Slide 79 text

render() { return ( ( { ... this.setState({ ... }) }} /> : {

Slide 80

Slide 80 text

barStyle="light-content" /> ( { ... this.setState({ ... }) }} /> : { this.setState({ ... }) ... }} />} /> )} extraData={this.state} keyExtractor={item => item.label} />

Slide 81

Slide 81 text

data={this.state.items} renderItem={(item, index) => ( { ... this.setState({ ... }) }} /> : { this.setState({ ... }) ... }} />} /> )} extraData={this.state} keyExtractor={item => item.label}

Slide 82

Slide 82 text

/> ( { ... this.setState({ ... }) }} /> : { this.setState({ ... }) ... }} />} /> )} extraData={this.state} keyExtractor={item => item.label} /> ); } const styles = StyleSheet.create({ container: { borderRadius: 5, const styles = StyleSheet.create({ container: { borderRadius: 5, backgroundColor: "#F3F3F3", marginHorizontal: 10, marginVertical: 5, } });

Slide 83

Slide 83 text

data={this.state.items} renderItem={(item, index) => ( { ... this.setState({ ... }) }} /> : { this.setState({ ... }) ... }} />} /> )} extraData={this.state} keyExtractor={item => item.label}

Slide 84

Slide 84 text

renderItem={(item, index) => ( { ... this.setState({ ... }) }} /> : { this.setState({ ... }) ... }} />} /> )} extraData={this.state} keyExtractor={item => item.label} /> ); } const styles = StyleSheet.create({ container: { borderRadius: 5, backgroundColor: "#F3F3F3", marginHorizontal: 10, const styles = StyleSheet.create({ container: { borderRadius: 5, backgroundColor: "#F3F3F3", marginHorizontal: 10, marginVertical: 5, }, icon: { marginEnd: 10, padding: 20 }, });

Slide 85

Slide 85 text

title={item.label} containerStyle={styles.container} rightIcon={this.state.playingId == index ? { ... this.setState({ ... }) }} /> : { this.setState({ ... }) ... }} />} /> )} extraData={this.state}

Slide 86

Slide 86 text

render() { return ( ( { ... this.setState({ ... }) }} /> : { this.setState({ ... }) ... }} />} /> )} extraData={this.state} keyExtractor={item => item.label} /> ); } const styles = StyleSheet.create({ container: { borderRadius: 5, backgroundColor: "#F3F3F3", marginHorizontal: 10, marginVertical: 5, }, icon: { marginEnd: 10, padding: 20 }, });

Slide 87

Slide 87 text

@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Flutter vs React - Flutter Example"), ), body: Container( child: ListView.builder( itemBuilder: (BuildContext context, int index) { return Material( child: Container( margin: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0), padding: const EdgeInsets.symmetric( horizontal: 15.0, vertical: 10.0), decoration: new BoxDecoration( color: Colors.grey.shade300.withOpacity(0.3), borderRadius: new BorderRadius.circular(5.0), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(_items[index].name), IconButton( icon: _playing ? new Icon(Icons.stop) : new Icon(Icons.play_arrow), onPressed: () { ... setState(() { ... }); }), ], ), ), ); }, itemCount: _items.length, ), ), ); }

Slide 88

Slide 88 text

@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Flutter vs React - Flutter Example"), ), body: Container( child: ListView.builder( itemBuilder: (BuildContext context, int index) { return Material( child: Container( margin: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0), padding: const EdgeInsets.symmetric( horizontal: 15.0, vertical: 10.0), decoration: new BoxDecoration( color: Colors.grey.shade300.withOpacity(0.3), borderRadius: new BorderRadius.circular(5.0), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(_items[index].name),

Slide 89

Slide 89 text

@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Flutter vs React - Flutter Example"), ), body: Container( child: ListView.builder( itemBuilder: (BuildContext context, int index) { return Material( child: Container( margin: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0), padding: const EdgeInsets.symmetric( horizontal: 15.0, vertical: 10.0), decoration: new BoxDecoration( color: Colors.grey.shade300.withOpacity(0.3), borderRadius: new BorderRadius.circular(5.0), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(_items[index].name),

Slide 90

Slide 90 text

@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Flutter vs React - Flutter Example"), ), body: Container( child: ListView.builder( itemBuilder: (BuildContext context, int index) { return Material( child: Container( margin: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0), padding: const EdgeInsets.symmetric( horizontal: 15.0, vertical: 10.0), decoration: new BoxDecoration( color: Colors.grey.shade300.withOpacity(0.3), borderRadius: new BorderRadius.circular(5.0), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(_items[index].name),

Slide 91

Slide 91 text

@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Flutter vs React - Flutter Example"), ), body: Container( child: ListView.builder( itemBuilder: (BuildContext context, int index) { return Material( child: Container( margin: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0), padding: const EdgeInsets.symmetric( horizontal: 15.0, vertical: 10.0), decoration: new BoxDecoration( color: Colors.grey.shade300.withOpacity(0.3), borderRadius: new BorderRadius.circular(5.0), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(_items[index].name),

Slide 92

Slide 92 text

Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Flutter vs React - Flutter Example"), ), body: Container( child: ListView.builder( itemBuilder: (BuildContext context, int index) { return Material( child: Container( margin: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0), padding: const EdgeInsets.symmetric( horizontal: 15.0, vertical: 10.0), decoration: new BoxDecoration( color: Colors.grey.shade300.withOpacity(0.3), borderRadius: new BorderRadius.circular(5.0), ), child: Row(

Slide 93

Slide 93 text

@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Flutter vs React - Flutter Example"), ), body: Container( child: ListView.builder( itemBuilder: (BuildContext context, int index) { return Material( child: Container( margin: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0), padding: const EdgeInsets.symmetric( horizontal: 15.0, vertical: 10.0), decoration: new BoxDecoration( color: Colors.grey.shade300.withOpacity(0.3), borderRadius: new BorderRadius.circular(5.0), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(_items[index].name), IconButton( icon: _playing ? new Icon(Icons.stop) : new Icon(Icons.play_arrow), onPressed: () { ... setState(() { ... ( ... ... >

Slide 94

Slide 94 text

body: Container( child: ListView.builder( itemBuilder: (BuildContext context, int index) { return Material( child: Container( margin: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0), padding: const EdgeInsets.symmetric( horizontal: 15.0, vertical: 10.0), decoration: new BoxDecoration( color: Colors.grey.shade300.withOpacity(0.3), borderRadius: new BorderRadius.circular(5.0), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(_items[index].name), IconButton( icon: _playing ? new Icon(Icons.stop) : new Icon(Icons.play_arrow), onPressed: () { ... setState(() {

Slide 95

Slide 95 text

horizontal: 15.0, vertical: 10.0), decoration: new BoxDecoration( color: Colors.grey.shade300.withOpacity(0.3), borderRadius: new BorderRadius.circular(5.0), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(_items[index].name), IconButton( icon: _playing ? new Icon(Icons.stop) : new Icon(Icons.play_arrow), onPressed: () { ... setState(() { ... }); }), ], ), ), ); },

Slide 96

Slide 96 text

@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Flutter vs React - Flutter Example"), ), body: Container( child: ListView.builder( itemBuilder: (BuildContext context, int index) { return Material( child: Container( margin: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0), padding: const EdgeInsets.symmetric( horizontal: 15.0, vertical: 10.0), decoration: new BoxDecoration( color: Colors.grey.shade300.withOpacity(0.3), borderRadius: new BorderRadius.circular(5.0), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(_items[index].name), IconButton( icon: _playing ? new Icon(Icons.stop) : new Icon(Icons.play_arrow), onPressed: () { ... setState(() { ... }); }), ], ), ), ); }, itemCount: _items.length, ), ), ); }

Slide 97

Slide 97 text

mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(_items[index].name), IconButton( icon: _playing ? new Icon(Icons.stop) : new Icon(Icons.play_arrow), onPressed: () { ... setState(() { ... }); }), ], ), ), ); }, itemCount: _items.length,

Slide 98

Slide 98 text

@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Flutter vs React - Flutter Example"), ), body: Container( child: ListView.builder( itemBuilder: (BuildContext context, int index) { return Material( child: Container( margin: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0), padding: const EdgeInsets.symmetric( horizontal: 15.0, vertical: 10.0), decoration: new BoxDecoration( color: Colors.grey.shade300.withOpacity(0.3), borderRadius: new BorderRadius.circular(5.0), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(_items[index].name), IconButton( icon: _playing ? new Icon(Icons.stop) : new Icon(Icons.play_arrow), onPressed: () { ... setState(() { ... }); }), ], ), ), ); }, itemCount: _items.length, ), ), ); }

Slide 99

Slide 99 text

Source Code bit.ly/react-native-sample bit.ly/flutter-sample bit.ly/flutter-better-sample

Slide 100

Slide 100 text

CONCLUSIONS

Slide 101

Slide 101 text

Crossplatform • Crossplatform is not bad but… IS NOT better than native • It’s a choice with compromises based on specific situation • If trouble became higher than benefits, make a step back

Slide 102

Slide 102 text

React Native or Flutter ? • Right now, React Native is more stable and solid • Flutter is the future • If Google does not drop it • Better performance that other framework • Dart is a more modern language

Slide 103

Slide 103 text

Flutter for Web • Rendering using standards-based web technologies: HTML, CSS and JavaScript https://flutter.dev/web

Slide 104

Slide 104 text

Desktop support https://flutter.dev/desktop

Slide 105

Slide 105 text

Bibliography / Useful Links • https://flutter.dev/docs/development/ui/widgets-intro • https://flutter.dev/docs/get-started/flutter-for/react-native-devs • https://facebook.github.io/react-native/docs/components-and-apis.html • https://levelup.gitconnected.com/wait-what-happens-when-my-react-native-application-starts-an-in-depth-look-inside-react-native-5f306ef3250f • https://flutter.dev/docs/resources/faq • https://flutter.dev/docs/resources/technical-overview • https://speakerdeck.com/mkonicek/under-the-hood-of-react-native • https://speakerdeck.com/frantic/react-native-under-the-hood • https://www.youtube.com/watch?v=rReCzR6DMEM • https://facebook.github.io/react-native/blog/2016/03/24/introducing-hot-reloading • https://flutter.dev/docs/development/tools/hot-reload • https://reactjs.org/blog/2015/12/18/react-components-elements-and-instances.html • https://reactjs.org/docs/reconciliation.html • https://flutter.dev/docs/resources/inside-flutter • https://github.com/flutter/flutter/wiki/Add-Flutter-to-existing-apps • https://facebook.github.io/react-native/docs/integration-with-existing-apps • https://medium.com/snapp-mobile/multi-vs-cross-platform-in-the-age-of-flutter-6e76920028b6 • https://medium.com/dartlang/announcing-dart-2-80ba01f43b6 • https://medium.com/airbnb-engineering/sunsetting-react-native-1868ba28e30a • https://medium.com/flutter-io/hummingbird-building-flutter-for-the-web-e687c2a023a8

Slide 106

Slide 106 text

THANK YOU! twitter.com/marcoGomier github.com/prof18 marco.gomiero.93[at]gmail[dot]com marcogomiero.com