SlideShare a Scribd company logo
React Native:
Crossplatform fast dive
1
About me
— Vladimir Ivanov - Lead software engineer
— More than 6 years in Android development
— Wide interest in Mobile technologies
— Happy father of a wonderful son
2
Why not crossplatform?
1. Lack of specialists
2. UX concerns
3. God damn javascript
3
Why crossplatform?
1. Cheap development
2. because rapid
3. 3x faster than native approach
4. Native UX, at last
4
How is was to dive a year ago?
1. Install node
2. Install android/ios sdk
3. For android: install java, download platforms,
emulators, build tools
4. Learn React Native
5. ???
6. PROFIT!11
5
How it is now?
1. Install node
2. Learn React Native
3. create-react-native-app
4. Done
6
Let’s dive
7
Simple start
$ brew install node
8
Simple start
$ brew install node
$ npm install -g create-react-native-app
9
Simple start
$ brew install node
$ npm install -g create-react-native-app
$ create-react-native-app github
10
Simple start
$ brew install node
$ npm install -g create-react-native-app
$ create-react-native-app github
$ cd github
11
Simple start
$ brew install node
$ npm install -g create-react-native-app
$ create-react-native-app github
$ cd github
$ npm start
12
What we get
$ ls -l
13
What have we got
$ ls -l
App.js
App.test.js
README.md
app.json
node_modules
package.json
14
App.js
import React from 'react';
import { Text, View } from 'react-native';
export default class App extends React.Component {
render() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Hello, world!</Text>
</View>
);
}
}
15
16
App.js
import React from 'react';
17
App.js
import React from 'react’;
import { Text, View } from 'react-native';
18
App.js
import React from 'react’;
import { Text, View } from 'react-native’;
export default class App extends React.Component {
}
19
App.js
import React from 'react’;
import { Text, View } from 'react-native’;
export default class App extends React.Component {
render() {
}
}
20
App.js
import React from 'react’;
import { Text, View } from 'react-native’;
export default class App extends React.Component {
render() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Hello, world!</Text>
</View>
);
}
}
21
App.js
import React from 'react';
import { Text, View } from 'react-native';
export default class App extends React.Component {
render() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Hello, world!</Text>
</View>
);
}
}
22
App.js
<View style={{ flex: 1, justifyContent: 'center', alignItems:
'center' }}>
<View style={styles.container}>
23
App.js
return (
<View style={styles.container}>
…
</View>
);
…
const styles = {
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
}
};
24
App.js
<Text style={{ color: '#F00' }}>
Hello, world!
</Text>
25
Let’s make
something more
interesting
26
How?
1. React page is a component tree
2. Each piece of UI should be a component
27
4 main components
1. Logo
2. Inputs
3. Submit button
4. Optional message
28
Logo component
import React from 'react';
import {Image, View} from "react-native";
export default Logo = () => (
<View style={{alignItems: 'center'}}>
<Image
source={require('./../../../GitHub-Logo.png')}
/>
</View>
);
29
Logo component
export default Logo = () => (
…
);
30
Components can be
1. Functional - no lifecycle, no state, only JSX
2. Class based - lifecycle, state, usage in redux, etc.
31
Logo component
export default Logo = () => (
<View style={{alignItems: 'center'}}>
<Image
source={require('./../../../GitHub-Logo.png')}
/>
</View>
);
32
33
Login inputs
1. Render login input
2. Render password input(as hidden)
3. Pass somehow login and password to submit
function
34
Login inputs
import React from 'react';
import {View} from ‘react-native’;
import {FormInput} from 'react-native-elements';
export default LoginInputs = ({ onChangeValue }) => (
<View style={{ margin: 16 }}>
<FormInput
placeholder='login'
onChangeText={(value) => {
onChangeValue('login', value);
}}
/>
<FormInput
secureTextEntry
placeholder='password'
onChangeText={(value) => {
onChangeValue('password', value);
}}
/>
</View>
);
35
Login inputs
import React from 'react';
import {View} from ‘react-native’;
import {FormInput} from 'react-native-elements';
36
Login inputs
import React from 'react';
import {View} from ‘react-native’;
import {FormInput} from 'react-native-elements’;
37
Login inputs
import React from 'react’;
import {View} from ‘react-native’;
import {FormInput} from 'react-native-elements’;
38
Login inputs
export default LoginInputs = ({ onChangeValue }) => (
<View style={{ margin: 16 }}>
<FormInput
placeholder='login'
onChangeText={(value) => {
onChangeValue('login', value);
}}
/>
<FormInput
secureTextEntry
placeholder='password'
onChangeText={(value) => {
onChangeValue('password', value);
}}
/>
</View>
);
39
Login inputs
export default LoginInputs = ({ onChangeValue }) => (
…
);
40
Login inputs
export default LoginInputs = ({ onChangeValue }) => (
<View style={{ margin: 16 }}>
<FormInput
placeholder='login'
onChangeText={(value) => {
onChangeValue('login', value);
}}
/>
<FormInput
secureTextEntry
placeholder='password'
onChangeText={(value) => {
onChangeValue('password', value);
}}
/>
</View>);
);
41
Login inputs
export default LoginInputs = ({ onChangeValue }) => (
<View style={{ margin: 16 }}>
{ … }
</View>);
);
42
Login inputs
<View style={{ margin: 16 }}>
<FormInput
placeholder='login'
onChangeText={(value) => {
onChangeValue('login', value);
}}
/>
<FormInput
secureTextEntry
placeholder='password'
onChangeText={(value) => {
onChangeValue('password', value);
}}
/>
</View>);
43
Login inputs
<View style={{ margin: 16 }}>
<FormInput
placeholder='login'
onChangeText={(value) => {
onChangeValue('login', value);
}}
/>
<FormInput />
</View>);
44
Login inputs
<View style={{ margin: 16 }}>
<FormInput />
<FormInput
secureTextEntry
placeholder='password'
onChangeText={(value) => {
onChangeValue('password', value);
}}
/>
</View>);
45
LoginScreen.js
render() {
const {container} = styles;
return (
<View style={container}>
<Logo />
<LoginInputs …/>
</View>
)
}
46
47
Login inputs
Value propagation
48
Component state
1. Each class based component has state
2. State is no more than a javascript object
3. Updating state is async, but this is not really
important now
4. Updating state happens with this.setState() function
49
Saving login and password to screen state
…
class LoginScreen extends Component {
state = { error: null };
…
}
50
Saving login and password to screen state
…
class LoginScreen extends Component {
state = { error: null };
onChangeValue = (prop, value) => {
this.setState({ [prop]: value });
};
…
}
51
Saving login and password to screen state
{ login: ‘v’ }
{ login: ‘vl’ }
{ login: ‘vli’ }
…
{ login: ‘vlivanov’, password: ’1’ }
{ login: ‘vlivanov’, password: ’12’ }
…
{ login: ‘vlivanov’, password: ’123abc123’ }
52
Submit button
<Button
raised
title='LOGIN'
backgroundColor="#00F"
icon={{name: 'cached'}}
onPress={this.doLogin}
/>
53
LoginScreen.js
render() {
return (
<View style={container}>
<Logo />
<LoginInputs onChangeValue={…}/>
<Button
…
/>
</View>
)
}
54
55
Submit button
<Button
…
onPress={this.doLogin}
/>
56
Submit button
doLogin = async () => {
const { login, password } = this.state;
let result = await loginAsync(login, password);
this.setState({
loggedIn: result.error === undefined,
error: result.error
});
};
57
Submit button
doLogin = async () => {
const { login, password } = this.state;
…
};
58
Submit button
doLogin = async () => {
const { login, password } = this.state;
let result = await loginAsync(login, password);
…
};
59
Submit button
doLogin = async () => {
const { login, password } = this.state;
let result = await loginAsync(login, password);
this.setState({
loggedIn: result.error === undefined,
error: result.error
});
};
60
loginAsync
export const loginAsync = async (login, password) => {
let base64 = encode(`${login}:${password}`);
try {
let result = await fetch('https://api.github.com/user', {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Basic ' + base64
},
});
if (result.status === 200) {
return {
user: JSON.parse(result._bodyInit),
auth: base64
};
} else {
return { error: `Failed to login with ${result.status}` };
}
} catch (error) {
console.log("[LoginActions] error = " + JSON.stringify(error));
return { error: `Failed to login with ${result.error}` };
}
};
61
loginAsync
export const loginAsync = async (login, password) => {
let base64 = encode(`${login}:${password}`);
…
};
62
loginAsync
export const loginAsync = async (login, password) => {
let base64 = encode(`${login}:${password}`);
try {
let result = await fetch('https://api.github.com/user', …);
…
} catch (error) {
…
}
};
63
loginAsync
export const loginAsync = async (login, password) => {
let base64 = encode(`${login}:${password}`);
try {
let result = await fetch('https://api.github.com/user', {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Basic ' + base64
},
});
…
} catch (error) {
…
}
};
64
loginAsync
export const loginAsync = async (login, password) => {
let base64 = …
try {
let result = await fetch('https://api.github.com/user', …);
if (result.status === 200) {
return {
user: JSON.parse(result._bodyInit),
auth: base64
};
}
…
} catch (error) {
…
}
};
65
loginAsync
export const loginAsync = async (login, password) => {
let base64 = …;
try {
let result = await fetch('https://api.github.com/user', …);
if (result.status === 200) {
return { … }
} else {
return { error: `Failed to login with ${result.status}` };
}
} catch (error) {
return { error: `Failed to login with ${error}` };
}
};
66
LoginScreen.js
render() {
const {container, successMessage, errorMessage} = styles;
return (
<View style={container}>
<Logo />
<LoginInputs …/>
<Button
…
/>
{this.state.loggedIn && <Text style={successMessage}>Logged in!</Text>}
{this.state.error && <Text style={errorMessage}>{this.state.error}</Text>}
</View>
)
}
67
doLogin
doLogin = async () => {
const { login, password } = this.state;
let result = await loginAsync(login, password);
this.setState({
loggedIn: result.error === undefined,
error: result.error
});
};
68
69
Немного статистики
— 153 строки
— 1 Час времени разработки
70
Полезные ссылки
— https://facebook.github.io/react-native/docs/getting-
started.html
— https://www.udemy.com/the-complete-react-native-
and-redux-course/
— https://expo.io
— https://css-tricks.com/snippets/css/a-guide-to-
flexbox/
71
Вопросы?
72

More Related Content

What's hot

Workshop 23: ReactJS, React & Redux testing
Workshop 23: ReactJS, React & Redux testingWorkshop 23: ReactJS, React & Redux testing
Workshop 23: ReactJS, React & Redux testing
Visual Engineering
 
Rails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript Using CoffeeScript, Backbone.js and JasmineRails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Raimonds Simanovskis
 
Why Every Tester Should Learn Ruby
Why Every Tester Should Learn RubyWhy Every Tester Should Learn Ruby
Why Every Tester Should Learn Ruby
Raimonds Simanovskis
 
Rails on Oracle 2011
Rails on Oracle 2011Rails on Oracle 2011
Rails on Oracle 2011
Raimonds Simanovskis
 
Javascript Promises/Q Library
Javascript Promises/Q LibraryJavascript Promises/Q Library
Javascript Promises/Q Library
async_io
 
Introduction to Asynchronous scala
Introduction to Asynchronous scalaIntroduction to Asynchronous scala
Introduction to Asynchronous scala
Stratio
 
Keeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and WebpackKeeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and Webpack
Ignacio Martín
 
CoffeeScript - TechTalk 21/10/2013
CoffeeScript - TechTalk 21/10/2013CoffeeScript - TechTalk 21/10/2013
CoffeeScript - TechTalk 21/10/2013
Spyros Ioakeimidis
 
Akka Cluster in Java - JCConf 2015
Akka Cluster in Java - JCConf 2015Akka Cluster in Java - JCConf 2015
Akka Cluster in Java - JCConf 2015
Jiayun Zhou
 
Javascript Module Patterns
Javascript Module PatternsJavascript Module Patterns
Javascript Module Patterns
Nicholas Jansma
 
Workshop 8: Templating: Handlebars, DustJS
Workshop 8: Templating: Handlebars, DustJSWorkshop 8: Templating: Handlebars, DustJS
Workshop 8: Templating: Handlebars, DustJS
Visual Engineering
 
Angular2
Angular2Angular2
Sane Sharding with Akka Cluster
Sane Sharding with Akka ClusterSane Sharding with Akka Cluster
Sane Sharding with Akka Cluster
miciek
 
Symfony tips and tricks
Symfony tips and tricksSymfony tips and tricks
Symfony tips and tricks
Javier Eguiluz
 
When Enterprise Java Micro Profile meets Angular
When Enterprise Java Micro Profile meets AngularWhen Enterprise Java Micro Profile meets Angular
When Enterprise Java Micro Profile meets Angular
Antonio Goncalves
 
Running a Scalable And Reliable Symfony2 Application in Cloud (Symfony Sweden...
Running a Scalable And Reliable Symfony2 Application in Cloud (Symfony Sweden...Running a Scalable And Reliable Symfony2 Application in Cloud (Symfony Sweden...
Running a Scalable And Reliable Symfony2 Application in Cloud (Symfony Sweden...
Ville Mattila
 
Introduction to es6
Introduction to es6Introduction to es6
Introduction to es6
NexThoughts Technologies
 
Cracking JWT tokens: a tale of magic, Node.JS and parallel computing
Cracking JWT tokens: a tale of magic, Node.JS and parallel computingCracking JWT tokens: a tale of magic, Node.JS and parallel computing
Cracking JWT tokens: a tale of magic, Node.JS and parallel computing
Luciano Mammino
 
Akka Futures and Akka Remoting
Akka Futures  and Akka RemotingAkka Futures  and Akka Remoting
Akka Futures and Akka Remoting
Knoldus Inc.
 
Promise pattern
Promise patternPromise pattern
Promise pattern
Sebastiaan Deckers
 

What's hot (20)

Workshop 23: ReactJS, React & Redux testing
Workshop 23: ReactJS, React & Redux testingWorkshop 23: ReactJS, React & Redux testing
Workshop 23: ReactJS, React & Redux testing
 
Rails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript Using CoffeeScript, Backbone.js and JasmineRails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
 
Why Every Tester Should Learn Ruby
Why Every Tester Should Learn RubyWhy Every Tester Should Learn Ruby
Why Every Tester Should Learn Ruby
 
Rails on Oracle 2011
Rails on Oracle 2011Rails on Oracle 2011
Rails on Oracle 2011
 
Javascript Promises/Q Library
Javascript Promises/Q LibraryJavascript Promises/Q Library
Javascript Promises/Q Library
 
Introduction to Asynchronous scala
Introduction to Asynchronous scalaIntroduction to Asynchronous scala
Introduction to Asynchronous scala
 
Keeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and WebpackKeeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and Webpack
 
CoffeeScript - TechTalk 21/10/2013
CoffeeScript - TechTalk 21/10/2013CoffeeScript - TechTalk 21/10/2013
CoffeeScript - TechTalk 21/10/2013
 
Akka Cluster in Java - JCConf 2015
Akka Cluster in Java - JCConf 2015Akka Cluster in Java - JCConf 2015
Akka Cluster in Java - JCConf 2015
 
Javascript Module Patterns
Javascript Module PatternsJavascript Module Patterns
Javascript Module Patterns
 
Workshop 8: Templating: Handlebars, DustJS
Workshop 8: Templating: Handlebars, DustJSWorkshop 8: Templating: Handlebars, DustJS
Workshop 8: Templating: Handlebars, DustJS
 
Angular2
Angular2Angular2
Angular2
 
Sane Sharding with Akka Cluster
Sane Sharding with Akka ClusterSane Sharding with Akka Cluster
Sane Sharding with Akka Cluster
 
Symfony tips and tricks
Symfony tips and tricksSymfony tips and tricks
Symfony tips and tricks
 
When Enterprise Java Micro Profile meets Angular
When Enterprise Java Micro Profile meets AngularWhen Enterprise Java Micro Profile meets Angular
When Enterprise Java Micro Profile meets Angular
 
Running a Scalable And Reliable Symfony2 Application in Cloud (Symfony Sweden...
Running a Scalable And Reliable Symfony2 Application in Cloud (Symfony Sweden...Running a Scalable And Reliable Symfony2 Application in Cloud (Symfony Sweden...
Running a Scalable And Reliable Symfony2 Application in Cloud (Symfony Sweden...
 
Introduction to es6
Introduction to es6Introduction to es6
Introduction to es6
 
Cracking JWT tokens: a tale of magic, Node.JS and parallel computing
Cracking JWT tokens: a tale of magic, Node.JS and parallel computingCracking JWT tokens: a tale of magic, Node.JS and parallel computing
Cracking JWT tokens: a tale of magic, Node.JS and parallel computing
 
Akka Futures and Akka Remoting
Akka Futures  and Akka RemotingAkka Futures  and Akka Remoting
Akka Futures and Akka Remoting
 
Promise pattern
Promise patternPromise pattern
Promise pattern
 

Similar to Mobile Open Day: React Native: Crossplatform fast dive

A re introduction to webpack - reactfoo - mumbai
A re introduction to webpack - reactfoo - mumbaiA re introduction to webpack - reactfoo - mumbai
A re introduction to webpack - reactfoo - mumbai
Praveen Puglia
 
React native tour
React native tourReact native tour
React native tour
Magdiel Duarte
 
React Native: JS MVC Meetup #15
React Native: JS MVC Meetup #15React Native: JS MVC Meetup #15
React Native: JS MVC Meetup #15
Rob Gietema
 
EWD 3 Training Course Part 41: Building a React.js application with QEWD, Part 5
EWD 3 Training Course Part 41: Building a React.js application with QEWD, Part 5EWD 3 Training Course Part 41: Building a React.js application with QEWD, Part 5
EWD 3 Training Course Part 41: Building a React.js application with QEWD, Part 5
Rob Tweed
 
React native by example by Vadim Ruban
React native by example by Vadim RubanReact native by example by Vadim Ruban
React native by example by Vadim Ruban
Lohika_Odessa_TechTalks
 
Building Universal Web Apps with React ForwardJS 2017
Building Universal Web Apps with React ForwardJS 2017Building Universal Web Apps with React ForwardJS 2017
Building Universal Web Apps with React ForwardJS 2017
Elyse Kolker Gordon
 
React native introduction
React native introductionReact native introduction
React native introduction
InnerFood
 
Connect.js - Exploring React.Native
Connect.js - Exploring React.NativeConnect.js - Exploring React.Native
Connect.js - Exploring React.Native
joshcjensen
 
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)
Ontico
 
Introduction to React for Frontend Developers
Introduction to React for Frontend DevelopersIntroduction to React for Frontend Developers
Introduction to React for Frontend Developers
Sergio Nakamura
 
React native app with type script tutorial
React native app with type script tutorialReact native app with type script tutorial
React native app with type script tutorial
Katy Slemon
 
Vue JS @ MindDoc. The progressive road to online therapy
Vue JS @ MindDoc. The progressive road to online therapyVue JS @ MindDoc. The progressive road to online therapy
Vue JS @ MindDoc. The progressive road to online therapy
Darío Blanco Iturriaga
 
Building a js widget
Building a js widgetBuilding a js widget
Building a js widget
Tudor Barbu
 
MOPCON 2014 - Best software architecture in app development
MOPCON 2014 - Best software architecture in app developmentMOPCON 2014 - Best software architecture in app development
MOPCON 2014 - Best software architecture in app development
anistar sung
 
Lessons from a year of building apps with React Native
Lessons from a year of building apps with React NativeLessons from a year of building apps with React Native
Lessons from a year of building apps with React Native
Ryan Boland
 
React: JSX and Top Level API
React: JSX and Top Level APIReact: JSX and Top Level API
React: JSX and Top Level API
Fabio Biondi
 
Django + Vue, JavaScript de 3ª generación para modernizar Django
Django + Vue, JavaScript de 3ª generación para modernizar DjangoDjango + Vue, JavaScript de 3ª generación para modernizar Django
Django + Vue, JavaScript de 3ª generación para modernizar Django
Javier Abadía
 
Reduxing like a pro
Reduxing like a proReduxing like a pro
Reduxing like a pro
Boris Dinkevich
 
Java Airline Reservation System – Travel Smarter, Not Harder.pdf
Java Airline Reservation System – Travel Smarter, Not Harder.pdfJava Airline Reservation System – Travel Smarter, Not Harder.pdf
Java Airline Reservation System – Travel Smarter, Not Harder.pdf
SudhanshiBakre1
 
React native introduction
React native introductionReact native introduction
React native introduction
InnerFood
 

Similar to Mobile Open Day: React Native: Crossplatform fast dive (20)

A re introduction to webpack - reactfoo - mumbai
A re introduction to webpack - reactfoo - mumbaiA re introduction to webpack - reactfoo - mumbai
A re introduction to webpack - reactfoo - mumbai
 
React native tour
React native tourReact native tour
React native tour
 
React Native: JS MVC Meetup #15
React Native: JS MVC Meetup #15React Native: JS MVC Meetup #15
React Native: JS MVC Meetup #15
 
EWD 3 Training Course Part 41: Building a React.js application with QEWD, Part 5
EWD 3 Training Course Part 41: Building a React.js application with QEWD, Part 5EWD 3 Training Course Part 41: Building a React.js application with QEWD, Part 5
EWD 3 Training Course Part 41: Building a React.js application with QEWD, Part 5
 
React native by example by Vadim Ruban
React native by example by Vadim RubanReact native by example by Vadim Ruban
React native by example by Vadim Ruban
 
Building Universal Web Apps with React ForwardJS 2017
Building Universal Web Apps with React ForwardJS 2017Building Universal Web Apps with React ForwardJS 2017
Building Universal Web Apps with React ForwardJS 2017
 
React native introduction
React native introductionReact native introduction
React native introduction
 
Connect.js - Exploring React.Native
Connect.js - Exploring React.NativeConnect.js - Exploring React.Native
Connect.js - Exploring React.Native
 
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)
 
Introduction to React for Frontend Developers
Introduction to React for Frontend DevelopersIntroduction to React for Frontend Developers
Introduction to React for Frontend Developers
 
React native app with type script tutorial
React native app with type script tutorialReact native app with type script tutorial
React native app with type script tutorial
 
Vue JS @ MindDoc. The progressive road to online therapy
Vue JS @ MindDoc. The progressive road to online therapyVue JS @ MindDoc. The progressive road to online therapy
Vue JS @ MindDoc. The progressive road to online therapy
 
Building a js widget
Building a js widgetBuilding a js widget
Building a js widget
 
MOPCON 2014 - Best software architecture in app development
MOPCON 2014 - Best software architecture in app developmentMOPCON 2014 - Best software architecture in app development
MOPCON 2014 - Best software architecture in app development
 
Lessons from a year of building apps with React Native
Lessons from a year of building apps with React NativeLessons from a year of building apps with React Native
Lessons from a year of building apps with React Native
 
React: JSX and Top Level API
React: JSX and Top Level APIReact: JSX and Top Level API
React: JSX and Top Level API
 
Django + Vue, JavaScript de 3ª generación para modernizar Django
Django + Vue, JavaScript de 3ª generación para modernizar DjangoDjango + Vue, JavaScript de 3ª generación para modernizar Django
Django + Vue, JavaScript de 3ª generación para modernizar Django
 
Reduxing like a pro
Reduxing like a proReduxing like a pro
Reduxing like a pro
 
Java Airline Reservation System – Travel Smarter, Not Harder.pdf
Java Airline Reservation System – Travel Smarter, Not Harder.pdfJava Airline Reservation System – Travel Smarter, Not Harder.pdf
Java Airline Reservation System – Travel Smarter, Not Harder.pdf
 
React native introduction
React native introductionReact native introduction
React native introduction
 

More from epamspb

Mobile Open Day: Things I wish I'd known about Core Data before getting married
Mobile Open Day: Things I wish I'd known about Core Data before getting marriedMobile Open Day: Things I wish I'd known about Core Data before getting married
Mobile Open Day: Things I wish I'd known about Core Data before getting married
epamspb
 
#ITsubbotnik Spring 2017: Sergey Chibirev/Andrei Ortyashov "Умный дом своими ...
#ITsubbotnik Spring 2017: Sergey Chibirev/Andrei Ortyashov "Умный дом своими ...#ITsubbotnik Spring 2017: Sergey Chibirev/Andrei Ortyashov "Умный дом своими ...
#ITsubbotnik Spring 2017: Sergey Chibirev/Andrei Ortyashov "Умный дом своими ...
epamspb
 
#ITsubbotnik Spring 2017: Stepan Rakitin "Создаем отказоустойчивые распределе...
#ITsubbotnik Spring 2017: Stepan Rakitin "Создаем отказоустойчивые распределе...#ITsubbotnik Spring 2017: Stepan Rakitin "Создаем отказоустойчивые распределе...
#ITsubbotnik Spring 2017: Stepan Rakitin "Создаем отказоустойчивые распределе...
epamspb
 
#ITsubbotnik Spring 2017: Rustam Kadyrov "Как приструнить зоопарк из микросер...
#ITsubbotnik Spring 2017: Rustam Kadyrov "Как приструнить зоопарк из микросер...#ITsubbotnik Spring 2017: Rustam Kadyrov "Как приструнить зоопарк из микросер...
#ITsubbotnik Spring 2017: Rustam Kadyrov "Как приструнить зоопарк из микросер...
epamspb
 
ITsubbotnik Spring 2017: Dmitriy Yatsyuk "Готовое комплексное инфраструктурно...
ITsubbotnik Spring 2017: Dmitriy Yatsyuk "Готовое комплексное инфраструктурно...ITsubbotnik Spring 2017: Dmitriy Yatsyuk "Готовое комплексное инфраструктурно...
ITsubbotnik Spring 2017: Dmitriy Yatsyuk "Готовое комплексное инфраструктурно...
epamspb
 
#ITsubbotnik Spring 2017: Sergey Chernolyas "JPA for NoSQL"
#ITsubbotnik Spring 2017: Sergey Chernolyas "JPA for NoSQL"#ITsubbotnik Spring 2017: Sergey Chernolyas "JPA for NoSQL"
#ITsubbotnik Spring 2017: Sergey Chernolyas "JPA for NoSQL"
epamspb
 
#ITsubbotnik Spring 2017: Roman Iovlev "Java edge in test automation"
#ITsubbotnik Spring 2017: Roman Iovlev "Java edge in test automation"#ITsubbotnik Spring 2017: Roman Iovlev "Java edge in test automation"
#ITsubbotnik Spring 2017: Roman Iovlev "Java edge in test automation"
epamspb
 
#ITsubbotnik Spring 2017: Dmitrii Nikitko "Deep learning for understanding of...
#ITsubbotnik Spring 2017: Dmitrii Nikitko "Deep learning for understanding of...#ITsubbotnik Spring 2017: Dmitrii Nikitko "Deep learning for understanding of...
#ITsubbotnik Spring 2017: Dmitrii Nikitko "Deep learning for understanding of...
epamspb
 
#ITsubbotnik Spring 2017: Roman Dimitrenko "Building Paas with the HashiStack"
#ITsubbotnik Spring 2017: Roman Dimitrenko "Building Paas with the HashiStack"#ITsubbotnik Spring 2017: Roman Dimitrenko "Building Paas with the HashiStack"
#ITsubbotnik Spring 2017: Roman Dimitrenko "Building Paas with the HashiStack"
epamspb
 
#ITsubbotnik Spring 2017: Mikhail Khludnev "Search like %SQL%"
#ITsubbotnik Spring 2017: Mikhail Khludnev "Search like %SQL%"#ITsubbotnik Spring 2017: Mikhail Khludnev "Search like %SQL%"
#ITsubbotnik Spring 2017: Mikhail Khludnev "Search like %SQL%"
epamspb
 
#ITsubbotnik Spring 2017: Andriy Filatov "Ансамбль солёных поваров: сравнивае...
#ITsubbotnik Spring 2017: Andriy Filatov "Ансамбль солёных поваров: сравнивае...#ITsubbotnik Spring 2017: Andriy Filatov "Ансамбль солёных поваров: сравнивае...
#ITsubbotnik Spring 2017: Andriy Filatov "Ансамбль солёных поваров: сравнивае...
epamspb
 
#ITsubbotnik Spring 2017: Anton Shapin, Denis Klykov "Visualization, storage ...
#ITsubbotnik Spring 2017: Anton Shapin, Denis Klykov "Visualization, storage ...#ITsubbotnik Spring 2017: Anton Shapin, Denis Klykov "Visualization, storage ...
#ITsubbotnik Spring 2017: Anton Shapin, Denis Klykov "Visualization, storage ...
epamspb
 
#ITsubbotnik Spring 2017: Sergey Mishanin "Report Portal. Руководство для аде...
#ITsubbotnik Spring 2017: Sergey Mishanin "Report Portal. Руководство для аде...#ITsubbotnik Spring 2017: Sergey Mishanin "Report Portal. Руководство для аде...
#ITsubbotnik Spring 2017: Sergey Mishanin "Report Portal. Руководство для аде...
epamspb
 

More from epamspb (13)

Mobile Open Day: Things I wish I'd known about Core Data before getting married
Mobile Open Day: Things I wish I'd known about Core Data before getting marriedMobile Open Day: Things I wish I'd known about Core Data before getting married
Mobile Open Day: Things I wish I'd known about Core Data before getting married
 
#ITsubbotnik Spring 2017: Sergey Chibirev/Andrei Ortyashov "Умный дом своими ...
#ITsubbotnik Spring 2017: Sergey Chibirev/Andrei Ortyashov "Умный дом своими ...#ITsubbotnik Spring 2017: Sergey Chibirev/Andrei Ortyashov "Умный дом своими ...
#ITsubbotnik Spring 2017: Sergey Chibirev/Andrei Ortyashov "Умный дом своими ...
 
#ITsubbotnik Spring 2017: Stepan Rakitin "Создаем отказоустойчивые распределе...
#ITsubbotnik Spring 2017: Stepan Rakitin "Создаем отказоустойчивые распределе...#ITsubbotnik Spring 2017: Stepan Rakitin "Создаем отказоустойчивые распределе...
#ITsubbotnik Spring 2017: Stepan Rakitin "Создаем отказоустойчивые распределе...
 
#ITsubbotnik Spring 2017: Rustam Kadyrov "Как приструнить зоопарк из микросер...
#ITsubbotnik Spring 2017: Rustam Kadyrov "Как приструнить зоопарк из микросер...#ITsubbotnik Spring 2017: Rustam Kadyrov "Как приструнить зоопарк из микросер...
#ITsubbotnik Spring 2017: Rustam Kadyrov "Как приструнить зоопарк из микросер...
 
ITsubbotnik Spring 2017: Dmitriy Yatsyuk "Готовое комплексное инфраструктурно...
ITsubbotnik Spring 2017: Dmitriy Yatsyuk "Готовое комплексное инфраструктурно...ITsubbotnik Spring 2017: Dmitriy Yatsyuk "Готовое комплексное инфраструктурно...
ITsubbotnik Spring 2017: Dmitriy Yatsyuk "Готовое комплексное инфраструктурно...
 
#ITsubbotnik Spring 2017: Sergey Chernolyas "JPA for NoSQL"
#ITsubbotnik Spring 2017: Sergey Chernolyas "JPA for NoSQL"#ITsubbotnik Spring 2017: Sergey Chernolyas "JPA for NoSQL"
#ITsubbotnik Spring 2017: Sergey Chernolyas "JPA for NoSQL"
 
#ITsubbotnik Spring 2017: Roman Iovlev "Java edge in test automation"
#ITsubbotnik Spring 2017: Roman Iovlev "Java edge in test automation"#ITsubbotnik Spring 2017: Roman Iovlev "Java edge in test automation"
#ITsubbotnik Spring 2017: Roman Iovlev "Java edge in test automation"
 
#ITsubbotnik Spring 2017: Dmitrii Nikitko "Deep learning for understanding of...
#ITsubbotnik Spring 2017: Dmitrii Nikitko "Deep learning for understanding of...#ITsubbotnik Spring 2017: Dmitrii Nikitko "Deep learning for understanding of...
#ITsubbotnik Spring 2017: Dmitrii Nikitko "Deep learning for understanding of...
 
#ITsubbotnik Spring 2017: Roman Dimitrenko "Building Paas with the HashiStack"
#ITsubbotnik Spring 2017: Roman Dimitrenko "Building Paas with the HashiStack"#ITsubbotnik Spring 2017: Roman Dimitrenko "Building Paas with the HashiStack"
#ITsubbotnik Spring 2017: Roman Dimitrenko "Building Paas with the HashiStack"
 
#ITsubbotnik Spring 2017: Mikhail Khludnev "Search like %SQL%"
#ITsubbotnik Spring 2017: Mikhail Khludnev "Search like %SQL%"#ITsubbotnik Spring 2017: Mikhail Khludnev "Search like %SQL%"
#ITsubbotnik Spring 2017: Mikhail Khludnev "Search like %SQL%"
 
#ITsubbotnik Spring 2017: Andriy Filatov "Ансамбль солёных поваров: сравнивае...
#ITsubbotnik Spring 2017: Andriy Filatov "Ансамбль солёных поваров: сравнивае...#ITsubbotnik Spring 2017: Andriy Filatov "Ансамбль солёных поваров: сравнивае...
#ITsubbotnik Spring 2017: Andriy Filatov "Ансамбль солёных поваров: сравнивае...
 
#ITsubbotnik Spring 2017: Anton Shapin, Denis Klykov "Visualization, storage ...
#ITsubbotnik Spring 2017: Anton Shapin, Denis Klykov "Visualization, storage ...#ITsubbotnik Spring 2017: Anton Shapin, Denis Klykov "Visualization, storage ...
#ITsubbotnik Spring 2017: Anton Shapin, Denis Klykov "Visualization, storage ...
 
#ITsubbotnik Spring 2017: Sergey Mishanin "Report Portal. Руководство для аде...
#ITsubbotnik Spring 2017: Sergey Mishanin "Report Portal. Руководство для аде...#ITsubbotnik Spring 2017: Sergey Mishanin "Report Portal. Руководство для аде...
#ITsubbotnik Spring 2017: Sergey Mishanin "Report Portal. Руководство для аде...
 

Recently uploaded

How a Second-hand/Pre-owned iPhone Becomes a Certified Premium Refurbished iP...
How a Second-hand/Pre-owned iPhone Becomes a Certified Premium Refurbished iP...How a Second-hand/Pre-owned iPhone Becomes a Certified Premium Refurbished iP...
How a Second-hand/Pre-owned iPhone Becomes a Certified Premium Refurbished iP...
Grest Grest.in
 
一比一原版(soton毕业证书)南安普顿大学毕业证如何办理
一比一原版(soton毕业证书)南安普顿大学毕业证如何办理一比一原版(soton毕业证书)南安普顿大学毕业证如何办理
一比一原版(soton毕业证书)南安普顿大学毕业证如何办理
sf3cfttw
 
eSIM and Virtual SIM Data Plans with GhostSims
eSIM and Virtual SIM Data Plans with GhostSimseSIM and Virtual SIM Data Plans with GhostSims
eSIM and Virtual SIM Data Plans with GhostSims
Ghost Sims
 
一比一原版(hertfordshire毕业证书)赫特福德大学毕业证如何办理
一比一原版(hertfordshire毕业证书)赫特福德大学毕业证如何办理一比一原版(hertfordshire毕业证书)赫特福德大学毕业证如何办理
一比一原版(hertfordshire毕业证书)赫特福德大学毕业证如何办理
toynvu
 
一比一原版美国宾州州立大学毕业证(psu学位证)如何办理
一比一原版美国宾州州立大学毕业证(psu学位证)如何办理一比一原版美国宾州州立大学毕业证(psu学位证)如何办理
一比一原版美国宾州州立大学毕业证(psu学位证)如何办理
mjjbdpo2
 
一比一原版美国麻省大学波士顿分校毕业证如何办理
一比一原版美国麻省大学波士顿分校毕业证如何办理一比一原版美国麻省大学波士顿分校毕业证如何办理
一比一原版美国麻省大学波士顿分校毕业证如何办理
obaem
 

Recently uploaded (6)

How a Second-hand/Pre-owned iPhone Becomes a Certified Premium Refurbished iP...
How a Second-hand/Pre-owned iPhone Becomes a Certified Premium Refurbished iP...How a Second-hand/Pre-owned iPhone Becomes a Certified Premium Refurbished iP...
How a Second-hand/Pre-owned iPhone Becomes a Certified Premium Refurbished iP...
 
一比一原版(soton毕业证书)南安普顿大学毕业证如何办理
一比一原版(soton毕业证书)南安普顿大学毕业证如何办理一比一原版(soton毕业证书)南安普顿大学毕业证如何办理
一比一原版(soton毕业证书)南安普顿大学毕业证如何办理
 
eSIM and Virtual SIM Data Plans with GhostSims
eSIM and Virtual SIM Data Plans with GhostSimseSIM and Virtual SIM Data Plans with GhostSims
eSIM and Virtual SIM Data Plans with GhostSims
 
一比一原版(hertfordshire毕业证书)赫特福德大学毕业证如何办理
一比一原版(hertfordshire毕业证书)赫特福德大学毕业证如何办理一比一原版(hertfordshire毕业证书)赫特福德大学毕业证如何办理
一比一原版(hertfordshire毕业证书)赫特福德大学毕业证如何办理
 
一比一原版美国宾州州立大学毕业证(psu学位证)如何办理
一比一原版美国宾州州立大学毕业证(psu学位证)如何办理一比一原版美国宾州州立大学毕业证(psu学位证)如何办理
一比一原版美国宾州州立大学毕业证(psu学位证)如何办理
 
一比一原版美国麻省大学波士顿分校毕业证如何办理
一比一原版美国麻省大学波士顿分校毕业证如何办理一比一原版美国麻省大学波士顿分校毕业证如何办理
一比一原版美国麻省大学波士顿分校毕业证如何办理
 

Mobile Open Day: React Native: Crossplatform fast dive

  • 2. About me — Vladimir Ivanov - Lead software engineer — More than 6 years in Android development — Wide interest in Mobile technologies — Happy father of a wonderful son 2
  • 3. Why not crossplatform? 1. Lack of specialists 2. UX concerns 3. God damn javascript 3
  • 4. Why crossplatform? 1. Cheap development 2. because rapid 3. 3x faster than native approach 4. Native UX, at last 4
  • 5. How is was to dive a year ago? 1. Install node 2. Install android/ios sdk 3. For android: install java, download platforms, emulators, build tools 4. Learn React Native 5. ??? 6. PROFIT!11 5
  • 6. How it is now? 1. Install node 2. Learn React Native 3. create-react-native-app 4. Done 6
  • 8. Simple start $ brew install node 8
  • 9. Simple start $ brew install node $ npm install -g create-react-native-app 9
  • 10. Simple start $ brew install node $ npm install -g create-react-native-app $ create-react-native-app github 10
  • 11. Simple start $ brew install node $ npm install -g create-react-native-app $ create-react-native-app github $ cd github 11
  • 12. Simple start $ brew install node $ npm install -g create-react-native-app $ create-react-native-app github $ cd github $ npm start 12
  • 13. What we get $ ls -l 13
  • 14. What have we got $ ls -l App.js App.test.js README.md app.json node_modules package.json 14
  • 15. App.js import React from 'react'; import { Text, View } from 'react-native'; export default class App extends React.Component { render() { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Hello, world!</Text> </View> ); } } 15
  • 16. 16
  • 18. App.js import React from 'react’; import { Text, View } from 'react-native'; 18
  • 19. App.js import React from 'react’; import { Text, View } from 'react-native’; export default class App extends React.Component { } 19
  • 20. App.js import React from 'react’; import { Text, View } from 'react-native’; export default class App extends React.Component { render() { } } 20
  • 21. App.js import React from 'react’; import { Text, View } from 'react-native’; export default class App extends React.Component { render() { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Hello, world!</Text> </View> ); } } 21
  • 22. App.js import React from 'react'; import { Text, View } from 'react-native'; export default class App extends React.Component { render() { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Hello, world!</Text> </View> ); } } 22
  • 23. App.js <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <View style={styles.container}> 23
  • 24. App.js return ( <View style={styles.container}> … </View> ); … const styles = { container: { flex: 1, justifyContent: 'center', alignItems: 'center' } }; 24
  • 25. App.js <Text style={{ color: '#F00' }}> Hello, world! </Text> 25
  • 27. How? 1. React page is a component tree 2. Each piece of UI should be a component 27
  • 28. 4 main components 1. Logo 2. Inputs 3. Submit button 4. Optional message 28
  • 29. Logo component import React from 'react'; import {Image, View} from "react-native"; export default Logo = () => ( <View style={{alignItems: 'center'}}> <Image source={require('./../../../GitHub-Logo.png')} /> </View> ); 29
  • 30. Logo component export default Logo = () => ( … ); 30
  • 31. Components can be 1. Functional - no lifecycle, no state, only JSX 2. Class based - lifecycle, state, usage in redux, etc. 31
  • 32. Logo component export default Logo = () => ( <View style={{alignItems: 'center'}}> <Image source={require('./../../../GitHub-Logo.png')} /> </View> ); 32
  • 33. 33
  • 34. Login inputs 1. Render login input 2. Render password input(as hidden) 3. Pass somehow login and password to submit function 34
  • 35. Login inputs import React from 'react'; import {View} from ‘react-native’; import {FormInput} from 'react-native-elements'; export default LoginInputs = ({ onChangeValue }) => ( <View style={{ margin: 16 }}> <FormInput placeholder='login' onChangeText={(value) => { onChangeValue('login', value); }} /> <FormInput secureTextEntry placeholder='password' onChangeText={(value) => { onChangeValue('password', value); }} /> </View> ); 35
  • 36. Login inputs import React from 'react'; import {View} from ‘react-native’; import {FormInput} from 'react-native-elements'; 36
  • 37. Login inputs import React from 'react'; import {View} from ‘react-native’; import {FormInput} from 'react-native-elements’; 37
  • 38. Login inputs import React from 'react’; import {View} from ‘react-native’; import {FormInput} from 'react-native-elements’; 38
  • 39. Login inputs export default LoginInputs = ({ onChangeValue }) => ( <View style={{ margin: 16 }}> <FormInput placeholder='login' onChangeText={(value) => { onChangeValue('login', value); }} /> <FormInput secureTextEntry placeholder='password' onChangeText={(value) => { onChangeValue('password', value); }} /> </View> ); 39
  • 40. Login inputs export default LoginInputs = ({ onChangeValue }) => ( … ); 40
  • 41. Login inputs export default LoginInputs = ({ onChangeValue }) => ( <View style={{ margin: 16 }}> <FormInput placeholder='login' onChangeText={(value) => { onChangeValue('login', value); }} /> <FormInput secureTextEntry placeholder='password' onChangeText={(value) => { onChangeValue('password', value); }} /> </View>); ); 41
  • 42. Login inputs export default LoginInputs = ({ onChangeValue }) => ( <View style={{ margin: 16 }}> { … } </View>); ); 42
  • 43. Login inputs <View style={{ margin: 16 }}> <FormInput placeholder='login' onChangeText={(value) => { onChangeValue('login', value); }} /> <FormInput secureTextEntry placeholder='password' onChangeText={(value) => { onChangeValue('password', value); }} /> </View>); 43
  • 44. Login inputs <View style={{ margin: 16 }}> <FormInput placeholder='login' onChangeText={(value) => { onChangeValue('login', value); }} /> <FormInput /> </View>); 44
  • 45. Login inputs <View style={{ margin: 16 }}> <FormInput /> <FormInput secureTextEntry placeholder='password' onChangeText={(value) => { onChangeValue('password', value); }} /> </View>); 45
  • 46. LoginScreen.js render() { const {container} = styles; return ( <View style={container}> <Logo /> <LoginInputs …/> </View> ) } 46
  • 47. 47
  • 49. Component state 1. Each class based component has state 2. State is no more than a javascript object 3. Updating state is async, but this is not really important now 4. Updating state happens with this.setState() function 49
  • 50. Saving login and password to screen state … class LoginScreen extends Component { state = { error: null }; … } 50
  • 51. Saving login and password to screen state … class LoginScreen extends Component { state = { error: null }; onChangeValue = (prop, value) => { this.setState({ [prop]: value }); }; … } 51
  • 52. Saving login and password to screen state { login: ‘v’ } { login: ‘vl’ } { login: ‘vli’ } … { login: ‘vlivanov’, password: ’1’ } { login: ‘vlivanov’, password: ’12’ } … { login: ‘vlivanov’, password: ’123abc123’ } 52
  • 54. LoginScreen.js render() { return ( <View style={container}> <Logo /> <LoginInputs onChangeValue={…}/> <Button … /> </View> ) } 54
  • 55. 55
  • 57. Submit button doLogin = async () => { const { login, password } = this.state; let result = await loginAsync(login, password); this.setState({ loggedIn: result.error === undefined, error: result.error }); }; 57
  • 58. Submit button doLogin = async () => { const { login, password } = this.state; … }; 58
  • 59. Submit button doLogin = async () => { const { login, password } = this.state; let result = await loginAsync(login, password); … }; 59
  • 60. Submit button doLogin = async () => { const { login, password } = this.state; let result = await loginAsync(login, password); this.setState({ loggedIn: result.error === undefined, error: result.error }); }; 60
  • 61. loginAsync export const loginAsync = async (login, password) => { let base64 = encode(`${login}:${password}`); try { let result = await fetch('https://api.github.com/user', { method: 'GET', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json', 'Authorization': 'Basic ' + base64 }, }); if (result.status === 200) { return { user: JSON.parse(result._bodyInit), auth: base64 }; } else { return { error: `Failed to login with ${result.status}` }; } } catch (error) { console.log("[LoginActions] error = " + JSON.stringify(error)); return { error: `Failed to login with ${result.error}` }; } }; 61
  • 62. loginAsync export const loginAsync = async (login, password) => { let base64 = encode(`${login}:${password}`); … }; 62
  • 63. loginAsync export const loginAsync = async (login, password) => { let base64 = encode(`${login}:${password}`); try { let result = await fetch('https://api.github.com/user', …); … } catch (error) { … } }; 63
  • 64. loginAsync export const loginAsync = async (login, password) => { let base64 = encode(`${login}:${password}`); try { let result = await fetch('https://api.github.com/user', { method: 'GET', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json', 'Authorization': 'Basic ' + base64 }, }); … } catch (error) { … } }; 64
  • 65. loginAsync export const loginAsync = async (login, password) => { let base64 = … try { let result = await fetch('https://api.github.com/user', …); if (result.status === 200) { return { user: JSON.parse(result._bodyInit), auth: base64 }; } … } catch (error) { … } }; 65
  • 66. loginAsync export const loginAsync = async (login, password) => { let base64 = …; try { let result = await fetch('https://api.github.com/user', …); if (result.status === 200) { return { … } } else { return { error: `Failed to login with ${result.status}` }; } } catch (error) { return { error: `Failed to login with ${error}` }; } }; 66
  • 67. LoginScreen.js render() { const {container, successMessage, errorMessage} = styles; return ( <View style={container}> <Logo /> <LoginInputs …/> <Button … /> {this.state.loggedIn && <Text style={successMessage}>Logged in!</Text>} {this.state.error && <Text style={errorMessage}>{this.state.error}</Text>} </View> ) } 67
  • 68. doLogin doLogin = async () => { const { login, password } = this.state; let result = await loginAsync(login, password); this.setState({ loggedIn: result.error === undefined, error: result.error }); }; 68
  • 69. 69
  • 70. Немного статистики — 153 строки — 1 Час времени разработки 70
  • 71. Полезные ссылки — https://facebook.github.io/react-native/docs/getting- started.html — https://www.udemy.com/the-complete-react-native- and-redux-course/ — https://expo.io — https://css-tricks.com/snippets/css/a-guide-to- flexbox/ 71