SlideShare a Scribd company logo
How to React Native
Дмитрий Ульянов
JavaScript Developer
linkedin.com/in/drukas16
2 проекта
10 месяцев
2-3 JS разработчика
1 нативный разработчик
Кто использует React Native?
React
Чем хорош React?
Декларативность
Компонентный подход
One way data flow
Virtual DOM
React - это reconciler
ReactDOM - это renderer
React Native - тоже renderer
JS Native
Bridge
JS
Движок JavaScript Core.
Babel под капотом и свой
react-native пресет
Поддержка ES6 и ES7 фич
Полифиллы для ES6-ES7 методов
Object, Array и String;
а также для XMLHttpRequest, fetch,
консоли, тайм-аутов и тд.
Быстрый старт
Create React Native App
expo.io
How to React Native
Компоненты и стили
components/text/styles.js
import { StyleSheet } from 'react-native'
import * as Styles from '@styles'
export default StyleSheet.create({
default: {
fontSize: Styles.fontSizes.normal,
fontFamily: Styles.fonts.primaryFont,
color: Styles.colors.dark,
},
bold: {
fontWeight: ‘bold’
},
"/* other styles "*/
})
import { create } from ‘react-native-platform-stylesheet'
export default create({
default: {
fontSize: 18,
ios: {
fontFamily: 'Helvetica'
},
android: {
fontFamily: 'Roboto'
}
}
})
components/text/styles.js, платформозависимый код
import { create } from ‘react-native-platform-stylesheet'
export default create({
default: {
fontSize: 18,
ios: {
fontFamily: 'Helvetica'
},
android: {
fontFamily: 'Roboto'
}
}
})
components/text/styles.js, платформозависимый код
{
"/* ""... "*/
"rnpm": {
"assets": [
"fonts"
]
}
}
Кладем свои шрифты в fonts/
и обновляем package.json
$ react-native link assets
🎉🎉🎉🎉🎉
import styles from './styles.js'
const Text = ({children, ""...props}) !=> {
const {
bold, color, style: styleExtension,
""...otherProps
} = props
const style = [
styles.default, styleExtension,
bold !&& styles.bold, color !&& { color },
]
return (
<RNText {""...otherProps} style={style}>
{children}
"</RNText>
)
}
components/text/index.js, теперь со стилями
import styles from './styles.js'
const Text = ({children, ""...props}) !=> {
const {
bold, color, style: styleExtension,
""...otherProps
} = props
const style = [
styles.default, styleExtension,
bold !&& styles.bold, color !&& { color },
]
return (
<RNText {""...otherProps} style={style}>
{children}
"</RNText>
)
}
components/text/index.js, теперь со стилями
Использование компонента Text
<View>
<Text>Default text!"</Text>
<Text bold>Bold text!"</Text>
<Text color=“teal”>
Colored text!
"</Text>
"</View>
Использование компонента Text
<View>
<Text>Default text!"</Text>
<Text bold>Bold text!"</Text>
<Text color=“teal”>
Colored text!
"</Text>
"</View>
import Color from 'color'
const teal = Color('teal')
const gray = Color('dimgray')
const darker = color !=> color.darken(0.25)
const withOpacity = color !=> color.alpha(0.8)
export default {
dark: gray,
darker: darker(gray),
primary: teal,
primaryWithOpacity: withOpacity(teal),
}
styles/colors.js, используем npm модуль color
Платформозависимый код
const OS = Platform.OS "// 'android' or 'ios'
const platform = Platform.select({
ios: 'ios',
android: 'android'
})
├── filename.js "// кросплатформенный файл
├── filename.ios.js "// iOS
└── filename.android.js "// Android
Готовые компоненты
NativeBase
• MRN

• React Native Material Design

• React Native Material Kit
Анимации
Animated API LayoutAnimation API
class SpinningImage extends React.Component {
spinValue = new Animated.Value(0)
componentDidMount() { this.spin() }
spin = () => {
this.spinValue.setValue(0)
Animated.timing(this.spinValue, {
toValue: 1,
duration: 2000,
easing: Easing.linear,
useNativeDriver: true,
}).start(this.spin)
}
render() {
const spin = this.spinValue.interpolate({
inputRange: [0, 1],
outputRange: ['0deg', '360deg']
})
const transform = [{rotate: spin}]
const style = [styles.image, {transform}]
return (
<View>
<Animated.Image style={style}
source={myImage}/>
</View>
)
}
}
if (Platform.OS === 'android') {
UIManager.setLayoutAnimationEnabledExperimental(true);
}
class BoxWithSizeChanges extends React.Component {
state = {size: 200}
increaseSize = () => {
LayoutAnimation.spring()
// OR LayoutAnimation.configureNext(CUSTOM_CONFIG)
this.setState(state => ({size: state.size + 50}))
}
render() {
const {size} = this.state
const sizes = {height: size, width: size}
const style = [styles.box, sizes]
return (
<View>
<Box style={style}/>
<Button onPress={this.increaseSize}
title=‘Make him bigger!’/>
</View>
)
}
}
Animated API LayoutAnimation API
Real World React Native
Animations
oblador/react-native-animatable
<Animatable.Text animation="slideInDown"
iterationCount={5}
direction="alternate">
Up and down you go
</Animatable.Text>
<Animatable.Text animation="pulse"
easing="ease-out"
iterationCount="infinite"
style={{textAlign: 'center'}}>
❤
</Animatable.Text>
Навигация
React Native решения “из коробки”
NavigatorIOS
Navigator
NavigationExperimental
React Native решения “из коробки”
NavigatorIOS
Navigator
NavigationExperimental
Комьюнити решения
native-navigation
ex-navigation
react-native-navigation
react-navigation
react-native-redux-router
react-native-router-redux
react-native-route-navigator
react-native-simple-router
react-native-router
react-native-router-flux
react-router-navigation
react-community/react-navigation
wix/react-native-navigation
aksonov/react-native-router-flux
react-native-router-flux
Примеры, компоненты Router & Scene
<Router>
<Scene key="root">
<Scene key="home" component={Home} title="Home" "/>
<Scene key="about" component={About} title="About" "/>
<Scene key="wrapper" hideNavBar>
{"/* Nested scenes "*/}
"</Scene>
"</Scene>
"</Router>
Примеры, использование Actions
<Router>
<Scene key="root">
<Scene key="home" component={Home} title="Home" "/>
<Scene key="about" component={About} title="About" "/>
<Scene key="wrapper" hideNavBar>
{"/* Nested scenes "*/}
"</Scene>
"</Scene>
"</Router>
class About extends React.Component {
goHome = () "=> Actions['home']()
popHome = () "=> Actions.pop()
goHomeWithParams = () "=> Actions['home']({
iWillBeAvailableThroughPropsAtHome: ‘Hi there!’
})
"/* render etc "*/
}
Примеры, вспомогательные функции
const createScene = (key, {title, ""...props}) "=>
<Scene key={key}
sceneStyle={{padding: 64}}
renderLeftButton={() "=> <MenuToggle "/>}
title={(title "|| key).toUpperCase()}
{""...props} "/>
const Scenes = (
<Scene key="drawer" component={Drawer}>
<Scene key="wrapper">
{createScene('home', {component: Home, initial: true})}
{createScene('about', {component: About})}
{createScene('logout', {component: Logout, title: 'Log Out'})}
"</Scene>
"</Scene>
)
Примеры, Drawer
import Drawer from 'react-native-drawer'
import { DefaultRenderer, Keyboard } from 'react-native-router-flux'
"/* Drawer render "*/
const {navigationState, onNavigate} = props
return (
<Drawer {""...drawerProps}
open={navigationState.isOpen}
content={<WrappedComponent "/>}
onOpenStart={Keyboard.dismissKeyboard}>
<DefaultRenderer onNavigate={onNavigate}
navigationState={navigationState.children[0]} "/>
"</Drawer>
)
Примеры, Sub-scenes
const ProfileScenes = (
<Scene key="profile" component={Profile} title="My Profile">
<Scene key="profile/view" "/>
<Scene key="profile/edit" editMode
rightTitle="Save" onRight={saveProfile}
leftTitle="Cancel" onLeft={backToViewMode} "/>
<Scene key="profile/save" save "/>
"</Scene>
)
Примеры, Switch
<Scene
key="root"
tabs={true}
unmountScenes
component={connect(state "=> ({session: getSession(state)}))(Switch)}
selector={props "=> props.session ? 'main' : 'unauthorized'}
>
<Scene key="unauthorized" component={Unauthorized} "/>
<Scene key="main" component={Main} "/>
"</Scene>
react-navigation
Примеры, StackNavigator
StackNavigator({
Home: {
screen: HomeScreen,
navigationOptions: ({navigation}) "=> ({
title: 'Home',
headerRight: <Button onClick={navigation.navigate('somewhere')} "/>,
header: <CustomHeader "/>
"/* other screen props "*/
})
},
About,
"/* other screens "*/
}, {
headerMode: 'float',
initialRouteName: 'Home'
"/* other StackNavigator props "*/
})
Примеры, TabNavigator
TabNavigator({
Home: {
screen: HomeScreen,
navigationOptions: ({navigation}) "=> ({
tabBarLabel: 'Home',
tabBarIcon: ({tintColor}) "=> <Icon tint={tintColor}"/>
})
},
Feed,
"/* other tabs "*/
}, {
tabBarComponent: TabBarBottom,
tabBarOptions: {
activeTintColor: 'teal', "/* other tabBar props "*/
},
"/* other TabNavigator props "*/
})
Примеры, DrawerNavigator
DrawerNavigator({
Home: {
screen: HomeScreen,
navigationOptions: ({navigation}) "=> ({
drawerLabel: 'Home',
drawerIcon: ({tintColor}) "=> <Icon tint={tintColor}"/>
})
},
Profile,
"/* other tabs "*/
}, {
activeTintColor: 'teal',
contentComponent: props "=>
<ScrollView><DrawerItems {""...props} "/>"</ScrollView>
"/* other DrawerNavigator props "*/
})
Примеры, nested navigators
StackNavigator({
Tabs: {
screen: TabNavigator({ "/* tabs "*/ })
},
Stack: {
screen: StackNavigator({ "/* screens "*/ })
}
})
Примеры, screen props
this.props.navigation = {
dispatch,
goBack,
navigate,
"/* few more "*/
}
NavigationActions
NavigationActions.navigate({
routeName: 'Profile',
actions: [
NavigationActions.navigate({
routeName: 'Friends',
})
]
})
Работа с данными
Redux
Getting Started with Redux Building React Applications
with Idiomatic Redux
Набор джентльмена
redux && react-redux
redux-logger / redux-devtools
ducks modular structure
redux-actions
reselect
redux-saga
redux-persist
erikras/ducks-modular-redux
import { createAction, handleActions } from 'redux-actions'
import { moduleName } from './config' // moduleName = 'todosModule'
const initialState = {todos: []}
// MAY export action type, if it should be accessible
// in other parts of the app (e.g. redux-saga or other module)
const TODO_ADD = `${moduleName}/TODO_ADD`
// MUST export creators
export const addTodo = createAction(TODO_ADD)
// MUST export reducer as default
export default handleActions({
[TODO_ADD]: (state, {payload}) => ({todos: […state, payload]})
}, initialState);
// selectors, sagas, epics etc. MAY also be named export
redux/modules/todos/index.js
import { createSelector } from 'reselect'
import { moduleName } from ‘./config'
export const getTodos = state => state[moduleName].todos
export const getVisibilityFilter = state => state[moduleName].filter
export const getVisibleTodos = createSelector(
[getTodos, getVisibilityFilter],
(todos, visibilityFilter) => {
switch (filter) {
case 'SHOW_ALL':
return todos
case 'SHOW_COMPLETED':
return todos.filter(todo => todo.completed)
case 'SHOW_ACTIVE':
return todos.filter(todo => !todo.completed)
}
}
)
// todoList.js | import * as todosSelectors from '@modules/todos/selectors'
redux/modules/todos/selectors.jsreactjs/reselect
redux-thunk
redux-loop
redux-observable
5,402
1,214
2,992
8,129
Сайд-эффекты в Redux
redux-saga
Redux-Thunk
const a = <div onClick={
() => dispatch(actions.loadUser(userId))
}>{username}</div>
export const loadUser = userId =>
async dispatch => {
try {
const user = await userService.load(userId)
dispatch(userLoaded(user))
} catch (err) {
dispatch(userLoadFailed(err))
}
}
const a = <div onClick={
() => dispatch(actions.userNameClicked(userId))
}>{username}</div>
function * watchUserNameClickAndLoad () {
yield * takeLatest(USER_NAME_CLICKED, loadUser)
}
function * loadUser ({payload}) {
try {
const user = yield call(userService.load, payload)
yield put(userLoaded(user))
}
catch (err) {
yield put(userLoadFailed(err))
}
}
Императивный flow
+
Декларативные сайд-эффекты
+
Мощь генераторов
+
Огромное кол-во хелперов
Хелперы / Эффекты
• take (watcher)
• takeLatest (cancels previous)
• takeEvery
• call (blocking)
• fork (non-blocking)
• put (saga dispatch)
• select (saga mapState)
• delay
• cancel
• race && all (like in Promises)
etc.
redux-saga: login flow example
function * authorization () {
// Check the storage for cached token and profile
let [token, profile] = yield [
call(auth.getToken),
call(auth.getProfile),
]
// so now user may be logged in...
}
redux-saga: login flow example
// ...or may not, so we gonna wait for it
if (!token) {
const {payload: credentials} = yield take(profileActions.SIGN_IN)
const {response, error} = yield call(authRequest, credentials)
if (error) {
yield put(profileActions.signInFailed(error))
continue
}
token = response.token
profile = response.profile
yield [
call(auth.setToken, token),
call(auth.setProfile, profile),
]
}
redux-saga: login flow example
// Now when we have token and profile
// We can let user in
yield put(profileActions.signInSuccess({token, profile}))
yield take(profileActions.SIGN_OUT)
token = profile = null
yield [
call(auth.removeToken),
call(auth.removeProfile),
]
yield put(stackActions.clear())
yield put(profileActions.signOutSuccess())
redux-saga: login flow example
function * authorization () {
// Check the storage for cached token and profile
let [token, profile] = yield [call(auth.getToken), call(auth.getProfile)]
while (true) {
if (!token) {…} /* Receive token and profile data */
yield put(profileActions.signInSuccess({token, profile}))
yield take(profileActions.SIGN_OUT)
/* Other signOut stuff */
}
}
Ignite
https://infinite.red/ignite
Заходите на Medium
Twitter
@reactjs @reactnative @dan_abramov@Vjeux
@JI @grabbou @tylermcginnis33 @koltal
По максимуму используйте PropTypes и DefaultProps
Для клавиатуры используйте KeyboardAvoidingView
Внимательно изучайте документацию
Не пренебрегайте селекторами
Найдите в себе силы разобраться с Redux-Saga - не пожалеете
Не забывайте убивать console.log, когда льете в прод
И конечно же пишите на React Native - он крутой
inline-советы напоследок
Вопросы?
linkedin.com/in/drukas16

More Related Content

PDF
A tour of React Native
PDF
React Native Workshop - React Alicante
PDF
React Native - Workshop
PDF
React Native
PPT
PDF
React Native +Redux + ES6 (Updated)
PDF
The Gist of React Native
PDF
JavaScript, React Native and Performance at react-europe 2016
A tour of React Native
React Native Workshop - React Alicante
React Native - Workshop
React Native
React Native +Redux + ES6 (Updated)
The Gist of React Native
JavaScript, React Native and Performance at react-europe 2016

What's hot (20)

PDF
Introduction to React Native Workshop
PPTX
Hands on react native
PDF
An Overview of the React Ecosystem
PDF
Ryan Christiani I Heard React Was Good
PDF
Introduction to react native
PPTX
React Native for ReactJS Devs
PDF
Introduction to React Native
PDF
React Native custom components
PPTX
Creating books app with react native
PDF
Intro To React Native
PDF
Optimizing React Native views for pre-animation
PDF
React Native: React Meetup 3
PDF
Philip Shurpik "Architecting React Native app"
PPTX
React Native: Introduction
PDF
From zero to hero with React Native!
PDF
React Native "A Bad Idea Or A Game Changer" at Code Mania 101
PDF
What's This React Native Thing I Keep Hearing About?
PDF
Putting the Native in React Native - React Native Boston
PDF
Server side rendering with React and Symfony
PDF
Getting Started with React-Nathan Smith
Introduction to React Native Workshop
Hands on react native
An Overview of the React Ecosystem
Ryan Christiani I Heard React Was Good
Introduction to react native
React Native for ReactJS Devs
Introduction to React Native
React Native custom components
Creating books app with react native
Intro To React Native
Optimizing React Native views for pre-animation
React Native: React Meetup 3
Philip Shurpik "Architecting React Native app"
React Native: Introduction
From zero to hero with React Native!
React Native "A Bad Idea Or A Game Changer" at Code Mania 101
What's This React Native Thing I Keep Hearing About?
Putting the Native in React Native - React Native Boston
Server side rendering with React and Symfony
Getting Started with React-Nathan Smith
Ad

Similar to How to React Native (20)

PDF
React Native: JS MVC Meetup #15
PPTX
JS Fest 2018. Илья Иванов. Введение в React-Native
PPTX
React native introduction
PDF
React native buy one get one free?!
PPTX
React native by example by Vadim Ruban
PPTX
React Native
PPTX
React native introduction
PDF
Workshop 25: React Native - Components
PDF
Burn your grass with react native
PPTX
Flutter vs React: взгляд нативщика / Александр Смирнов (Splyt)
PDF
An iOS Developer's Perspective on React Native
PPTX
Academy PRO: React native - navigation
PDF
Introduzione a React Native - Facebook Developer Circle Rome
PDF
React Native Components Building Blocks for Dynamic Apps.pdf
PDF
Modular Navigation with React Navigation
PDF
Connect.js - Exploring React.Native
PDF
React Native for multi-platform mobile applications
PPTX
Ilya Ivanov - Advanced React-Native
PPTX
Lecture 2 Styling and Layout in React Native.pptx
PPTX
React Native & NativeScript
React Native: JS MVC Meetup #15
JS Fest 2018. Илья Иванов. Введение в React-Native
React native introduction
React native buy one get one free?!
React native by example by Vadim Ruban
React Native
React native introduction
Workshop 25: React Native - Components
Burn your grass with react native
Flutter vs React: взгляд нативщика / Александр Смирнов (Splyt)
An iOS Developer's Perspective on React Native
Academy PRO: React native - navigation
Introduzione a React Native - Facebook Developer Circle Rome
React Native Components Building Blocks for Dynamic Apps.pdf
Modular Navigation with React Navigation
Connect.js - Exploring React.Native
React Native for multi-platform mobile applications
Ilya Ivanov - Advanced React-Native
Lecture 2 Styling and Layout in React Native.pptx
React Native & NativeScript
Ad

Recently uploaded (20)

PPTX
Emphasizing It's Not The End 08 06 2025.pptx
PPTX
worship songs, in any order, compilation
PPTX
nose tajweed for the arabic alphabets for the responsive
PPTX
Self management and self evaluation presentation
PPTX
Learning-Plan-5-Policies-and-Practices.pptx
PDF
oil_refinery_presentation_v1 sllfmfls.pdf
PPTX
Role and Responsibilities of Bangladesh Coast Guard Base, Mongla Challenges
PPTX
fundraisepro pitch deck elegant and modern
PPTX
Relationship Management Presentation In Banking.pptx
PPTX
Impressionism_PostImpressionism_Presentation.pptx
PPTX
Tour Presentation Educational Activity.pptx
PDF
Swiggy’s Playbook: UX, Logistics & Monetization
PPTX
_ISO_Presentation_ISO 9001 and 45001.pptx
PPTX
Intro to ISO 9001 2015.pptx wareness raising
DOCX
"Project Management: Ultimate Guide to Tools, Techniques, and Strategies (2025)"
DOC
学位双硕士UTAS毕业证,墨尔本理工学院毕业证留学硕士毕业证
PPTX
Hydrogel Based delivery Cancer Treatment
PPTX
AcademyNaturalLanguageProcessing-EN-ILT-M02-Introduction.pptx
PPTX
An Unlikely Response 08 10 2025.pptx
PPTX
INTERNATIONAL LABOUR ORAGNISATION PPT ON SOCIAL SCIENCE
Emphasizing It's Not The End 08 06 2025.pptx
worship songs, in any order, compilation
nose tajweed for the arabic alphabets for the responsive
Self management and self evaluation presentation
Learning-Plan-5-Policies-and-Practices.pptx
oil_refinery_presentation_v1 sllfmfls.pdf
Role and Responsibilities of Bangladesh Coast Guard Base, Mongla Challenges
fundraisepro pitch deck elegant and modern
Relationship Management Presentation In Banking.pptx
Impressionism_PostImpressionism_Presentation.pptx
Tour Presentation Educational Activity.pptx
Swiggy’s Playbook: UX, Logistics & Monetization
_ISO_Presentation_ISO 9001 and 45001.pptx
Intro to ISO 9001 2015.pptx wareness raising
"Project Management: Ultimate Guide to Tools, Techniques, and Strategies (2025)"
学位双硕士UTAS毕业证,墨尔本理工学院毕业证留学硕士毕业证
Hydrogel Based delivery Cancer Treatment
AcademyNaturalLanguageProcessing-EN-ILT-M02-Introduction.pptx
An Unlikely Response 08 10 2025.pptx
INTERNATIONAL LABOUR ORAGNISATION PPT ON SOCIAL SCIENCE

How to React Native

  • 1. How to React Native
  • 3. 2 проекта 10 месяцев 2-3 JS разработчика 1 нативный разработчик
  • 8. React - это reconciler
  • 9. ReactDOM - это renderer
  • 10. React Native - тоже renderer
  • 12. JS Движок JavaScript Core. Babel под капотом и свой react-native пресет Поддержка ES6 и ES7 фич Полифиллы для ES6-ES7 методов Object, Array и String; а также для XMLHttpRequest, fetch, консоли, тайм-аутов и тд.
  • 14. Create React Native App expo.io
  • 17. components/text/styles.js import { StyleSheet } from 'react-native' import * as Styles from '@styles' export default StyleSheet.create({ default: { fontSize: Styles.fontSizes.normal, fontFamily: Styles.fonts.primaryFont, color: Styles.colors.dark, }, bold: { fontWeight: ‘bold’ }, "/* other styles "*/ })
  • 18. import { create } from ‘react-native-platform-stylesheet' export default create({ default: { fontSize: 18, ios: { fontFamily: 'Helvetica' }, android: { fontFamily: 'Roboto' } } }) components/text/styles.js, платформозависимый код
  • 19. import { create } from ‘react-native-platform-stylesheet' export default create({ default: { fontSize: 18, ios: { fontFamily: 'Helvetica' }, android: { fontFamily: 'Roboto' } } }) components/text/styles.js, платформозависимый код
  • 20. { "/* ""... "*/ "rnpm": { "assets": [ "fonts" ] } } Кладем свои шрифты в fonts/ и обновляем package.json $ react-native link assets 🎉🎉🎉🎉🎉
  • 21. import styles from './styles.js' const Text = ({children, ""...props}) !=> { const { bold, color, style: styleExtension, ""...otherProps } = props const style = [ styles.default, styleExtension, bold !&& styles.bold, color !&& { color }, ] return ( <RNText {""...otherProps} style={style}> {children} "</RNText> ) } components/text/index.js, теперь со стилями
  • 22. import styles from './styles.js' const Text = ({children, ""...props}) !=> { const { bold, color, style: styleExtension, ""...otherProps } = props const style = [ styles.default, styleExtension, bold !&& styles.bold, color !&& { color }, ] return ( <RNText {""...otherProps} style={style}> {children} "</RNText> ) } components/text/index.js, теперь со стилями
  • 23. Использование компонента Text <View> <Text>Default text!"</Text> <Text bold>Bold text!"</Text> <Text color=“teal”> Colored text! "</Text> "</View>
  • 24. Использование компонента Text <View> <Text>Default text!"</Text> <Text bold>Bold text!"</Text> <Text color=“teal”> Colored text! "</Text> "</View>
  • 25. import Color from 'color' const teal = Color('teal') const gray = Color('dimgray') const darker = color !=> color.darken(0.25) const withOpacity = color !=> color.alpha(0.8) export default { dark: gray, darker: darker(gray), primary: teal, primaryWithOpacity: withOpacity(teal), } styles/colors.js, используем npm модуль color
  • 26. Платформозависимый код const OS = Platform.OS "// 'android' or 'ios' const platform = Platform.select({ ios: 'ios', android: 'android' }) ├── filename.js "// кросплатформенный файл ├── filename.ios.js "// iOS └── filename.android.js "// Android
  • 29. • MRN • React Native Material Design • React Native Material Kit
  • 31. Animated API LayoutAnimation API class SpinningImage extends React.Component { spinValue = new Animated.Value(0) componentDidMount() { this.spin() } spin = () => { this.spinValue.setValue(0) Animated.timing(this.spinValue, { toValue: 1, duration: 2000, easing: Easing.linear, useNativeDriver: true, }).start(this.spin) } render() { const spin = this.spinValue.interpolate({ inputRange: [0, 1], outputRange: ['0deg', '360deg'] }) const transform = [{rotate: spin}] const style = [styles.image, {transform}] return ( <View> <Animated.Image style={style} source={myImage}/> </View> ) } } if (Platform.OS === 'android') { UIManager.setLayoutAnimationEnabledExperimental(true); } class BoxWithSizeChanges extends React.Component { state = {size: 200} increaseSize = () => { LayoutAnimation.spring() // OR LayoutAnimation.configureNext(CUSTOM_CONFIG) this.setState(state => ({size: state.size + 50})) } render() { const {size} = this.state const sizes = {height: size, width: size} const style = [styles.box, sizes] return ( <View> <Box style={style}/> <Button onPress={this.increaseSize} title=‘Make him bigger!’/> </View> ) } }
  • 33. Real World React Native Animations
  • 34. oblador/react-native-animatable <Animatable.Text animation="slideInDown" iterationCount={5} direction="alternate"> Up and down you go </Animatable.Text> <Animatable.Text animation="pulse" easing="ease-out" iterationCount="infinite" style={{textAlign: 'center'}}> ❤ </Animatable.Text>
  • 36. React Native решения “из коробки” NavigatorIOS Navigator NavigationExperimental
  • 37. React Native решения “из коробки” NavigatorIOS Navigator NavigationExperimental
  • 41. Примеры, компоненты Router & Scene <Router> <Scene key="root"> <Scene key="home" component={Home} title="Home" "/> <Scene key="about" component={About} title="About" "/> <Scene key="wrapper" hideNavBar> {"/* Nested scenes "*/} "</Scene> "</Scene> "</Router>
  • 42. Примеры, использование Actions <Router> <Scene key="root"> <Scene key="home" component={Home} title="Home" "/> <Scene key="about" component={About} title="About" "/> <Scene key="wrapper" hideNavBar> {"/* Nested scenes "*/} "</Scene> "</Scene> "</Router> class About extends React.Component { goHome = () "=> Actions['home']() popHome = () "=> Actions.pop() goHomeWithParams = () "=> Actions['home']({ iWillBeAvailableThroughPropsAtHome: ‘Hi there!’ }) "/* render etc "*/ }
  • 43. Примеры, вспомогательные функции const createScene = (key, {title, ""...props}) "=> <Scene key={key} sceneStyle={{padding: 64}} renderLeftButton={() "=> <MenuToggle "/>} title={(title "|| key).toUpperCase()} {""...props} "/> const Scenes = ( <Scene key="drawer" component={Drawer}> <Scene key="wrapper"> {createScene('home', {component: Home, initial: true})} {createScene('about', {component: About})} {createScene('logout', {component: Logout, title: 'Log Out'})} "</Scene> "</Scene> )
  • 44. Примеры, Drawer import Drawer from 'react-native-drawer' import { DefaultRenderer, Keyboard } from 'react-native-router-flux' "/* Drawer render "*/ const {navigationState, onNavigate} = props return ( <Drawer {""...drawerProps} open={navigationState.isOpen} content={<WrappedComponent "/>} onOpenStart={Keyboard.dismissKeyboard}> <DefaultRenderer onNavigate={onNavigate} navigationState={navigationState.children[0]} "/> "</Drawer> )
  • 45. Примеры, Sub-scenes const ProfileScenes = ( <Scene key="profile" component={Profile} title="My Profile"> <Scene key="profile/view" "/> <Scene key="profile/edit" editMode rightTitle="Save" onRight={saveProfile} leftTitle="Cancel" onLeft={backToViewMode} "/> <Scene key="profile/save" save "/> "</Scene> ) Примеры, Switch <Scene key="root" tabs={true} unmountScenes component={connect(state "=> ({session: getSession(state)}))(Switch)} selector={props "=> props.session ? 'main' : 'unauthorized'} > <Scene key="unauthorized" component={Unauthorized} "/> <Scene key="main" component={Main} "/> "</Scene>
  • 47. Примеры, StackNavigator StackNavigator({ Home: { screen: HomeScreen, navigationOptions: ({navigation}) "=> ({ title: 'Home', headerRight: <Button onClick={navigation.navigate('somewhere')} "/>, header: <CustomHeader "/> "/* other screen props "*/ }) }, About, "/* other screens "*/ }, { headerMode: 'float', initialRouteName: 'Home' "/* other StackNavigator props "*/ })
  • 48. Примеры, TabNavigator TabNavigator({ Home: { screen: HomeScreen, navigationOptions: ({navigation}) "=> ({ tabBarLabel: 'Home', tabBarIcon: ({tintColor}) "=> <Icon tint={tintColor}"/> }) }, Feed, "/* other tabs "*/ }, { tabBarComponent: TabBarBottom, tabBarOptions: { activeTintColor: 'teal', "/* other tabBar props "*/ }, "/* other TabNavigator props "*/ })
  • 49. Примеры, DrawerNavigator DrawerNavigator({ Home: { screen: HomeScreen, navigationOptions: ({navigation}) "=> ({ drawerLabel: 'Home', drawerIcon: ({tintColor}) "=> <Icon tint={tintColor}"/> }) }, Profile, "/* other tabs "*/ }, { activeTintColor: 'teal', contentComponent: props "=> <ScrollView><DrawerItems {""...props} "/>"</ScrollView> "/* other DrawerNavigator props "*/ })
  • 50. Примеры, nested navigators StackNavigator({ Tabs: { screen: TabNavigator({ "/* tabs "*/ }) }, Stack: { screen: StackNavigator({ "/* screens "*/ }) } })
  • 51. Примеры, screen props this.props.navigation = { dispatch, goBack, navigate, "/* few more "*/ } NavigationActions NavigationActions.navigate({ routeName: 'Profile', actions: [ NavigationActions.navigate({ routeName: 'Friends', }) ] })
  • 53. Redux
  • 54. Getting Started with Redux Building React Applications with Idiomatic Redux
  • 55. Набор джентльмена redux && react-redux redux-logger / redux-devtools ducks modular structure redux-actions reselect redux-saga redux-persist
  • 56. erikras/ducks-modular-redux import { createAction, handleActions } from 'redux-actions' import { moduleName } from './config' // moduleName = 'todosModule' const initialState = {todos: []} // MAY export action type, if it should be accessible // in other parts of the app (e.g. redux-saga or other module) const TODO_ADD = `${moduleName}/TODO_ADD` // MUST export creators export const addTodo = createAction(TODO_ADD) // MUST export reducer as default export default handleActions({ [TODO_ADD]: (state, {payload}) => ({todos: […state, payload]}) }, initialState); // selectors, sagas, epics etc. MAY also be named export redux/modules/todos/index.js
  • 57. import { createSelector } from 'reselect' import { moduleName } from ‘./config' export const getTodos = state => state[moduleName].todos export const getVisibilityFilter = state => state[moduleName].filter export const getVisibleTodos = createSelector( [getTodos, getVisibilityFilter], (todos, visibilityFilter) => { switch (filter) { case 'SHOW_ALL': return todos case 'SHOW_COMPLETED': return todos.filter(todo => todo.completed) case 'SHOW_ACTIVE': return todos.filter(todo => !todo.completed) } } ) // todoList.js | import * as todosSelectors from '@modules/todos/selectors' redux/modules/todos/selectors.jsreactjs/reselect
  • 59. Redux-Thunk const a = <div onClick={ () => dispatch(actions.loadUser(userId)) }>{username}</div> export const loadUser = userId => async dispatch => { try { const user = await userService.load(userId) dispatch(userLoaded(user)) } catch (err) { dispatch(userLoadFailed(err)) } } const a = <div onClick={ () => dispatch(actions.userNameClicked(userId)) }>{username}</div> function * watchUserNameClickAndLoad () { yield * takeLatest(USER_NAME_CLICKED, loadUser) } function * loadUser ({payload}) { try { const user = yield call(userService.load, payload) yield put(userLoaded(user)) } catch (err) { yield put(userLoadFailed(err)) } }
  • 60. Императивный flow + Декларативные сайд-эффекты + Мощь генераторов + Огромное кол-во хелперов
  • 61. Хелперы / Эффекты • take (watcher) • takeLatest (cancels previous) • takeEvery • call (blocking) • fork (non-blocking) • put (saga dispatch) • select (saga mapState) • delay • cancel • race && all (like in Promises) etc.
  • 62. redux-saga: login flow example function * authorization () { // Check the storage for cached token and profile let [token, profile] = yield [ call(auth.getToken), call(auth.getProfile), ] // so now user may be logged in... }
  • 63. redux-saga: login flow example // ...or may not, so we gonna wait for it if (!token) { const {payload: credentials} = yield take(profileActions.SIGN_IN) const {response, error} = yield call(authRequest, credentials) if (error) { yield put(profileActions.signInFailed(error)) continue } token = response.token profile = response.profile yield [ call(auth.setToken, token), call(auth.setProfile, profile), ] }
  • 64. redux-saga: login flow example // Now when we have token and profile // We can let user in yield put(profileActions.signInSuccess({token, profile})) yield take(profileActions.SIGN_OUT) token = profile = null yield [ call(auth.removeToken), call(auth.removeProfile), ] yield put(stackActions.clear()) yield put(profileActions.signOutSuccess())
  • 65. redux-saga: login flow example function * authorization () { // Check the storage for cached token and profile let [token, profile] = yield [call(auth.getToken), call(auth.getProfile)] while (true) { if (!token) {…} /* Receive token and profile data */ yield put(profileActions.signInSuccess({token, profile})) yield take(profileActions.SIGN_OUT) /* Other signOut stuff */ } }
  • 69. Twitter @reactjs @reactnative @dan_abramov@Vjeux @JI @grabbou @tylermcginnis33 @koltal
  • 70. По максимуму используйте PropTypes и DefaultProps Для клавиатуры используйте KeyboardAvoidingView Внимательно изучайте документацию Не пренебрегайте селекторами Найдите в себе силы разобраться с Redux-Saga - не пожалеете Не забывайте убивать console.log, когда льете в прод И конечно же пишите на React Native - он крутой inline-советы напоследок