SlideShare ist ein Scribd-Unternehmen logo
1 von 72
Downloaden Sie, um offline zu lesen
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

Weitere ähnliche Inhalte

Was ist angesagt?

Workshop 23: ReactJS, React & Redux testing
Workshop 23: ReactJS, React & Redux testingWorkshop 23: ReactJS, React & Redux testing
Workshop 23: ReactJS, React & Redux testingVisual 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 JasmineRaimonds Simanovskis
 
Why Every Tester Should Learn Ruby
Why Every Tester Should Learn RubyWhy Every Tester Should Learn Ruby
Why Every Tester Should Learn RubyRaimonds Simanovskis
 
Javascript Promises/Q Library
Javascript Promises/Q LibraryJavascript Promises/Q Library
Javascript Promises/Q Libraryasync_io
 
Introduction to Asynchronous scala
Introduction to Asynchronous scalaIntroduction to Asynchronous scala
Introduction to Asynchronous scalaStratio
 
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 WebpackIgnacio Martín
 
CoffeeScript - TechTalk 21/10/2013
CoffeeScript - TechTalk 21/10/2013CoffeeScript - TechTalk 21/10/2013
CoffeeScript - TechTalk 21/10/2013Spyros Ioakeimidis
 
Akka Cluster in Java - JCConf 2015
Akka Cluster in Java - JCConf 2015Akka Cluster in Java - JCConf 2015
Akka Cluster in Java - JCConf 2015Jiayun Zhou
 
Javascript Module Patterns
Javascript Module PatternsJavascript Module Patterns
Javascript Module PatternsNicholas Jansma
 
Workshop 8: Templating: Handlebars, DustJS
Workshop 8: Templating: Handlebars, DustJSWorkshop 8: Templating: Handlebars, DustJS
Workshop 8: Templating: Handlebars, DustJSVisual Engineering
 
Sane Sharding with Akka Cluster
Sane Sharding with Akka ClusterSane Sharding with Akka Cluster
Sane Sharding with Akka Clustermiciek
 
Symfony tips and tricks
Symfony tips and tricksSymfony tips and tricks
Symfony tips and tricksJavier 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 AngularAntonio 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
 
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 computingLuciano Mammino
 
Akka Futures and Akka Remoting
Akka Futures  and Akka RemotingAkka Futures  and Akka Remoting
Akka Futures and Akka RemotingKnoldus Inc.
 

Was ist angesagt? (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
 

Ähnlich wie 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 - mumbaiPraveen Puglia
 
React Native: JS MVC Meetup #15
React Native: JS MVC Meetup #15React Native: JS MVC Meetup #15
React Native: JS MVC Meetup #15Rob 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 5Rob Tweed
 
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 2017Elyse Kolker Gordon
 
React native introduction
React native introductionReact native introduction
React native introductionInnerFood
 
Connect.js - Exploring React.Native
Connect.js - Exploring React.NativeConnect.js - Exploring React.Native
Connect.js - Exploring React.Nativejoshcjensen
 
Паразитируем на 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 DevelopersSergio 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 tutorialKaty 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 therapyDarío Blanco Iturriaga
 
Building a js widget
Building a js widgetBuilding a js widget
Building a js widgetTudor 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 developmentanistar 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 NativeRyan Boland
 
React: JSX and Top Level API
React: JSX and Top Level APIReact: JSX and Top Level API
React: JSX and Top Level APIFabio 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 DjangoJavier Abadía
 
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.pdfSudhanshiBakre1
 
React native introduction
React native introductionReact native introduction
React native introductionInnerFood
 

Ähnlich wie 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
 

Mehr von 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 marriedepamspb
 
#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
 

Mehr von 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. Руководство для аде...
 

Kürzlich hochgeladen

FULL ENJOY - 9999218229 Call Girls in {Mahipalpur}| Delhi NCR
FULL ENJOY - 9999218229 Call Girls in {Mahipalpur}| Delhi NCRFULL ENJOY - 9999218229 Call Girls in {Mahipalpur}| Delhi NCR
FULL ENJOY - 9999218229 Call Girls in {Mahipalpur}| Delhi NCRnishacall1
 
Leading Mobile App Development Companies in India (2).pdf
Leading Mobile App Development Companies in India (2).pdfLeading Mobile App Development Companies in India (2).pdf
Leading Mobile App Development Companies in India (2).pdfCWS Technology
 
9999266834 Call Girls In Noida Sector 52 (Delhi) Call Girl Service
9999266834 Call Girls In Noida Sector 52 (Delhi) Call Girl Service9999266834 Call Girls In Noida Sector 52 (Delhi) Call Girl Service
9999266834 Call Girls In Noida Sector 52 (Delhi) Call Girl Servicenishacall1
 
Powerful Love Spells in Arkansas, AR (310) 882-6330 Bring Back Lost Lover
Powerful Love Spells in Arkansas, AR (310) 882-6330 Bring Back Lost LoverPowerful Love Spells in Arkansas, AR (310) 882-6330 Bring Back Lost Lover
Powerful Love Spells in Arkansas, AR (310) 882-6330 Bring Back Lost LoverPsychicRuben LoveSpells
 
BDSM⚡Call Girls in Sector 71 Noida Escorts >༒8448380779 Escort Service
BDSM⚡Call Girls in Sector 71 Noida Escorts >༒8448380779 Escort ServiceBDSM⚡Call Girls in Sector 71 Noida Escorts >༒8448380779 Escort Service
BDSM⚡Call Girls in Sector 71 Noida Escorts >༒8448380779 Escort ServiceDelhi Call girls
 

Kürzlich hochgeladen (6)

FULL ENJOY - 9999218229 Call Girls in {Mahipalpur}| Delhi NCR
FULL ENJOY - 9999218229 Call Girls in {Mahipalpur}| Delhi NCRFULL ENJOY - 9999218229 Call Girls in {Mahipalpur}| Delhi NCR
FULL ENJOY - 9999218229 Call Girls in {Mahipalpur}| Delhi NCR
 
Obat Penggugur Kandungan Di Apotik Kimia Farma (087776558899)
Obat Penggugur Kandungan Di Apotik Kimia Farma (087776558899)Obat Penggugur Kandungan Di Apotik Kimia Farma (087776558899)
Obat Penggugur Kandungan Di Apotik Kimia Farma (087776558899)
 
Leading Mobile App Development Companies in India (2).pdf
Leading Mobile App Development Companies in India (2).pdfLeading Mobile App Development Companies in India (2).pdf
Leading Mobile App Development Companies in India (2).pdf
 
9999266834 Call Girls In Noida Sector 52 (Delhi) Call Girl Service
9999266834 Call Girls In Noida Sector 52 (Delhi) Call Girl Service9999266834 Call Girls In Noida Sector 52 (Delhi) Call Girl Service
9999266834 Call Girls In Noida Sector 52 (Delhi) Call Girl Service
 
Powerful Love Spells in Arkansas, AR (310) 882-6330 Bring Back Lost Lover
Powerful Love Spells in Arkansas, AR (310) 882-6330 Bring Back Lost LoverPowerful Love Spells in Arkansas, AR (310) 882-6330 Bring Back Lost Lover
Powerful Love Spells in Arkansas, AR (310) 882-6330 Bring Back Lost Lover
 
BDSM⚡Call Girls in Sector 71 Noida Escorts >༒8448380779 Escort Service
BDSM⚡Call Girls in Sector 71 Noida Escorts >༒8448380779 Escort ServiceBDSM⚡Call Girls in Sector 71 Noida Escorts >༒8448380779 Escort Service
BDSM⚡Call Girls in Sector 71 Noida Escorts >༒8448380779 Escort Service
 

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