Slide 1

Slide 1 text

September 2019 Introduction to React Native Victoria Quirante

Slide 2

Slide 2 text

Victoria Quirante I write code at Limenius. We build tailor-made projects, and provide consultancy and formation. And we are very happy users of React and React Native.

Slide 3

Slide 3 text

https://github.com/Limenius/workshop-react-native.git And run git fetch https://speakerdeck.com/victoriaq/react-native-workshop Before we start Please go to where you have cloned the repo of the project

Slide 4

Slide 4 text

Goal of the workshop To be able to estimate how long would it take you to create a first React Native project (and if you would enjoy it) A big part of it is the tooling

Slide 5

Slide 5 text

Roadmap: What is React Native Starting a project Working with Styles Layout Lists Navigation Networking Touching the native side

Slide 6

Slide 6 text

What is React Native?

Slide 7

Slide 7 text

Fundamental premise of React Give me a state and a render() method that depends on it and forget about how and when to render.

Slide 8

Slide 8 text

render() { return (
Click me! Clicks: {this.state.count}
) }

Slide 9

Slide 9 text

render() { return (
Click me! Clicks: {this.state.count}
) } render() { return ( Click me! Clicks: {this.state.count} ) }

Slide 10

Slide 10 text

render() { return (
Click me! Clicks: {this.state.count}
) } render() { return ( Click me! Clicks: {this.state.count} ) }

Slide 11

Slide 11 text

render() { return (
Click me! Clicks: {this.state.count}
) } render() { return ( Click me! Clicks: {this.state.count} ) } React Native

Slide 12

Slide 12 text

How is this possible Reconciliation Determines what parts of the tree have changed

Slide 13

Slide 13 text

How is this possible Reconciliation Determines what parts of the tree have changed Rendering Actually updates the app

Slide 14

Slide 14 text

How is this possible Reconciliation Determines what parts of the tree have changed Rendering Actually updates the app We can have several renderers

Slide 15

Slide 15 text

React targets Main react-dom react-native Web iOS android

Slide 16

Slide 16 text

React targets Main react-dom react-native Web iOS android But also

Slide 17

Slide 17 text

React targets Main react-dom react-native Web iOS android But also react-art react-canvas react-three ReactLiberty react-worker-dom

Slide 18

Slide 18 text

React targets Main react-dom react-native Web iOS android But also react-art react-canvas react-three ReactLiberty react-worker-dom react-konsul rax react-native react-blessed react-tvml

Slide 19

Slide 19 text

React targets Main react-dom react-native Web iOS android But also react-art react-canvas react-three ReactLiberty react-worker-dom react-konsul rax react-native react-blessed react-tvml React-GL react-vr react-hardware react-fs-renderer react-x11

Slide 20

Slide 20 text

React targets Main react-dom react-native Web iOS android But also react-art react-canvas react-three ReactLiberty react-worker-dom react-konsul rax react-native react-blessed react-tvml React-GL react-vr react-hardware react-fs-renderer react-x11 redocx react-titanium React-Gibbon react-pdf react-test-renderer

Slide 21

Slide 21 text

React targets Main react-dom react-native Web iOS android But also react-art react-canvas react-three ReactLiberty react-worker-dom react-konsul rax react-native react-blessed react-tvml React-GL react-vr react-hardware react-fs-renderer react-x11 redocx react-titanium React-Gibbon react-pdf react-test-renderer ink react-sketchapp

Slide 22

Slide 22 text

React targets Main react-dom react-native Web iOS android But also react-art react-canvas react-three ReactLiberty react-worker-dom react-konsul rax react-native react-blessed react-tvml React-GL react-vr react-hardware react-fs-renderer react-x11 redocx react-titanium React-Gibbon react-pdf react-test-renderer ink react-sketchapp And more

Slide 23

Slide 23 text

React blessed

Slide 24

Slide 24 text

React blessed

Slide 25

Slide 25 text

React Sketch.app

Slide 26

Slide 26 text

React VR Demo

Slide 27

Slide 27 text

How Native is React Native? JS Thread Business logic & Description of what components to render

Slide 28

Slide 28 text

How Native is React Native? JS Thread Main Thread UI manipulation with native components Business logic & Description of what components to render

Slide 29

Slide 29 text

How Native is React Native? JS Thread Main Thread UI manipulation with native components Business logic & Description of what components to render Bridge

Slide 30

Slide 30 text

How much code can we reuse? Tip: if you develop in one platform, test the app in the other from time to time 70%? 80%? 90%?

Slide 31

Slide 31 text

How to start a project

Slide 32

Slide 32 text

Option 1: expo $ npm install -g expo-cli $ expo init AwesomeProject

Slide 33

Slide 33 text

Option 1: expo Only JS, no iOS or Android code (outside node_modules) If you want to modify native code, $ npm run eject Uses the Expo app to test in real device Meant to have a quick way of trying react-native

Slide 34

Slide 34 text

Option 2: react-native init $ npm install -g react-native-cli $ react-native init AwesomeProject

Slide 35

Slide 35 text

Option 2: react-native init Complete project with native code More control Needed to use things like AppCenter Doesn’t need external tools to publish to the store

Slide 36

Slide 36 text

Getting our hands dirty

Slide 37

Slide 37 text

git clone https://github.com/Limenius/workshop-react-native.git You are supposed to have done this And then yarn install

Slide 38

Slide 38 text

git checkout master react-native run-ios And then Or react-native run-android

Slide 39

Slide 39 text

Debug tools Cmd + d (Cmd + r) ctrl+m / cmd+m

Slide 40

Slide 40 text

Play around Open app/App.js with an editor Hi there! Change the text in Try nesting Hi there! Amigo Try changing some styles welcome: { fontSize: 100, textAlign: 'center', margin: 10, }, Try placing a console.log(‘hi’) before return(… and see it in Chrome dev tools https://www.slideshare.net/nachomartin/react-native-workshop-react-alicante

Slide 41

Slide 41 text

Familiarize with errors What happens if we… remove a closing tag () Hi there! put text not wrapped in try to comment a JSX line with // return ( Hi there! ) have two root elements use wrong properties for styles ( rename flex -> flexo ) remove the words export default

Slide 42

Slide 42 text

Basic components

Slide 43

Slide 43 text

git checkout elements git reset HEAD --hard (To discard your changes)

Slide 44

Slide 44 text

Exercise: Play with the basic components app/App.js

Slide 45

Slide 45 text

Exercise: Build new components Can you build a new component combining others? Ideas: Image with footer (), two buttons that display different alerts Can you pass props to that component? Ideas: Pass the text of the footer with props, pass also the image, pass the titles of the buttons Can your build a component with local state? Ideas: Modify the counter to have a “minus 1” button

Slide 46

Slide 46 text

Style

Slide 47

Slide 47 text

No CSS. Everything is JS No class No dimensions in pixels No things like padding: 19 9 3 1 camelCased Use constants

Slide 48

Slide 48 text

StyleSheet const Styles = StyleSheet.create({ headline: { borderLeftColor: Colors.accent, borderLeftWidth: 9, backgroundColor: Colors.backgroundSection, paddingLeft: 18, paddingRight: 18, paddingTop: 9, paddingBottom: 9, }, })

Slide 49

Slide 49 text

Combination const Styles = StyleSheet.create({ headline: { borderLeftColor: Colors.accent, borderLeftWidth: 9, paddingLeft: 18, paddingRight: 18, paddingTop: 9, paddingBottom: 9, }, })

Slide 50

Slide 50 text

git checkout styles (To discard your changes) git reset HEAD --hard

Slide 51

Slide 51 text

We want to build this

Slide 52

Slide 52 text

Our first goal is to get this (We will practice layouts in the next section)

Slide 53

Slide 53 text

components/MovieHeader.js height: 210 fontWeight: ‘bold’ fontSize: FontSizes.LargeTitle 48x48, rounded backgroundColor: Colors.highlight color: Colors.text color: Colors.text fontWeight: ‘bold’ border: left, size 9, Colors.accent padding: 9, 18 backgroundColor: Colors.backgroundSection

Slide 54

Slide 54 text

Exercise 1 84x84 Colors.text, bold Container has: border at bottom size 1, Colors.subtleAccent and background is 'white' components/ListItemActor.js

Slide 55

Slide 55 text

Exercise 2 FontSizes.gigantic Colors.background Container has: a background with color: Colors.highlight components/MainHeader.js Image is 40x90 FontSizes.subhead With weight ‘200’ Colors.background

Slide 56

Slide 56 text

Dimensions import { Dimensions, } from 'react-native' const windowSize = Dimensions.get('window') mainImage: { height: windowSize.height /3, width: undefined }, components/MovieHeader.js

Slide 57

Slide 57 text

Dimensions import { Dimensions, } from 'react-native' const windowSize = Dimensions.get('window') mainImage: { height: windowSize.height /3, width: undefined }, Our image height depends on the Height of the window Use sparingly components/MovieHeader.js

Slide 58

Slide 58 text

Dimensions import { Dimensions, } from 'react-native' const windowSize = Dimensions.get('window') mainImage: { height: windowSize.height /3, width: undefined }, Our image height depends on the Height of the window Use sparingly Exercise: Can you make another style dependant of Dimensions? What will happen if the device is rotated? Can you find anything in the documentation to fix it? components/MovieHeader.js

Slide 59

Slide 59 text

Further reading https://www.okgrow.com/posts/react-native-styling-tips https://madebymany.com/stories/a-year-of-react-native-styling-part-1 https://emotion.sh/docs/@emotion/native Explore libraries to do CSS in JS

Slide 60

Slide 60 text

Layouts

Slide 61

Slide 61 text

This is flexbox realm flexDirection justifyContent alignItems alignSelf flex alignContent flexBasis flexGrow flexShrink flexWrap

Slide 62

Slide 62 text

This is flexbox realm flexDirection justifyContent alignItems alignSelf flex alignContent flexBasis flexGrow flexShrink flexWrap flexDirection: ‘column' flexDirection: ‘row’ (Default)

Slide 63

Slide 63 text

This is flexbox realm flexDirection justifyContent alignItems alignSelf flex alignContent flexBasis flexGrow flexShrink flexWrap flexDirection: ‘column' flexDirection: ‘row’ (Default) main direction cross direction

Slide 64

Slide 64 text

This is flexbox realm flexDirection justifyContent alignItems alignSelf flex alignContent flexBasis flexGrow flexShrink flexWrap flexDirection: ‘column' flexDirection: ‘row’ (Default) main direction cross direction cross direction main direction

Slide 65

Slide 65 text

This is flexbox realm flexDirection justifyContent alignItems alignSelf flex alignContent flexBasis flexGrow flexShrink flexWrap flexDirection: ‘column’ (Default) ‘flex-start’ ‘flex-end’ ‘center' ‘space-around’ ‘space-between’ flexDirection: ‘row’ (Default) ‘flex-start’ ‘flex-end’ ‘center' ‘space-around’ ‘space-between’

Slide 66

Slide 66 text

This is flexbox realm flexDirection justifyContent alignItems alignSelf flex alignContent flexBasis flexGrow flexShrink flexWrap flexDirection: ‘column’ (Default) ‘flex-start’ ‘flex-end’ ‘center' ‘stretch’ ‘baseline’ flexDirection: ‘row’ (Default) ‘flex-start’ ‘flex-end’ ‘center' ‘stretch’ ‘baseline’

Slide 67

Slide 67 text

This is flexbox realm flexDirection justifyContent alignItems alignSelf flex alignContent flexBasis flexGrow flexShrink flexWrap flexDirection: ‘row’ ‘baseline’

Slide 68

Slide 68 text

This is flexbox realm flexDirection justifyContent alignItems alignSelf flex alignContent flexBasis flexGrow flexShrink flexWrap flexDirection: ‘column’ alignSelf: ’end’

Slide 69

Slide 69 text

This is flexbox realm flexDirection justifyContent alignItems alignSelf flex alignContent flexBasis flexGrow flexShrink flexWrap flex: 1 flex: 0 flex: 0

Slide 70

Slide 70 text

This is flexbox realm flexDirection justifyContent alignItems alignSelf flex alignContent flexBasis flexGrow flexShrink flexWrap flex: 5 flex: 2 flex: 3

Slide 71

Slide 71 text

This is flexbox realm flexDirection justifyContent alignItems alignSelf flex alignContent flexBasis flexGrow flexShrink flexWrap flex: 0.5 flex: 0.2 flex: 0.3

Slide 72

Slide 72 text

This is flexbox realm flexDirection justifyContent alignItems alignSelf flex alignContent flexBasis flexGrow flexShrink flexWrap flex: 25 flex: 10 flex: 15

Slide 73

Slide 73 text

git checkout layout (To discard your changes) git reset HEAD --hard

Slide 74

Slide 74 text

Our goal

Slide 75

Slide 75 text

app/components/MovieHeader.js

Slide 76

Slide 76 text

app/components/MovieHeader.js

Slide 77

Slide 77 text

18 Exercise 1 app/components/ListItemActor.js

Slide 78

Slide 78 text

Exercise 2 Hint: create subviews if you need them Optional: can you come up with a different layout for any of our three components? app/components/MainHeader.js

Slide 79

Slide 79 text

Further reading https://facebook.github.io/yoga/docs/getting-started/ Docs: https://github.com/jondot/ReactNativeKatas Very good practice:

Slide 80

Slide 80 text

Lists

Slide 81

Slide 81 text

Lists are important in mobile

Slide 82

Slide 82 text

Naive lists, as in the web export default class Movie extends Component { constructor(props) { super(props) this.state = { movie: movies.find((movie) => movie.name === 'Pulp Fiction') } } render() { return ( { this.state.movie.actors.map(actor => ( ))} ) } } app/components/Movie.js

Slide 83

Slide 83 text

Naive lists, as in the web export default class Movie extends Component { constructor(props) { super(props) this.state = { movie: movies.find((movie) => movie.name === 'Pulp Fiction') } } render() { return ( { this.state.movie.actors.map(actor => ( ))} ) } } Important to help the reconciler do its work app/components/Movie.js

Slide 84

Slide 84 text

Exercise git checkout lists Can you build a list of movies in app/components/MovieList.js ? (To discard your changes) git reset HEAD --hard

Slide 85

Slide 85 text

FlatList Highly optimized List component Features: • Scroll loading (onEndReached). • Pull to refresh (onRefresh / refreshing). • Configurable viewability (VPV) callbacks (onViewableItemsChanged / viewabilityConfig). • Horizontal mode (horizontal). • Intelligent item and section separators. • Multi-column support (numColumns). • scrollToEnd, scrollToIndex, and scrollToItem.

Slide 86

Slide 86 text

FlatList render() { return ( } /> ) } app/components/Movie.js

Slide 87

Slide 87 text

FlatList

Slide 88

Slide 88 text

FlatList What about the keys?

Slide 89

Slide 89 text

FlatList What about the keys? item} renderItem={({item}) => } />

Slide 90

Slide 90 text

FlatList What about the keys? item} renderItem={({item}) => } />

Slide 91

Slide 91 text

FlatList Scrolleable area item} renderItem={({item}) => } />

Slide 92

Slide 92 text

FlatList Desired scrolleable area

Slide 93

Slide 93 text

FlatList Desired scrolleable area } keyExtractor={item => item} renderItem={({item}) => } />

Slide 94

Slide 94 text

FlatList Desired scrolleable area } keyExtractor={item => item} renderItem={({item}) => } />

Slide 95

Slide 95 text

Exercise Can you use FlatList in app/components/MovieList.js ? git checkout flatlists item => item reminder In this case works as function(item) { return item } git reset HEAD —hard (To discard your changes)

Slide 96

Slide 96 text

Further reading https://facebook.github.io/react-native/blog/2017/03/13/ better-list-views.html Read the docs of the components: FlatList SectionList VirtualizedList

Slide 97

Slide 97 text

Navigation

Slide 98

Slide 98 text

Navigation

Slide 99

Slide 99 text

react-navigation

Slide 100

Slide 100 text

Several options StackNavigator TabNavigator DrawerNavigator Or combine them

Slide 101

Slide 101 text

Several options StackNavigator TabNavigator DrawerNavigator Or combine them

Slide 102

Slide 102 text

Several options StackNavigator TabNavigator DrawerNavigator Or combine them

Slide 103

Slide 103 text

Several options StackNavigator TabNavigator DrawerNavigator Or combine them

Slide 104

Slide 104 text

git checkout navigation yarn install cd ios; pod install Let’s do it (To discard your changes) git reset HEAD --hard If iOS

Slide 105

Slide 105 text

Let’s do it const AppNavigator = createStackNavigator({ Home: { screen: MovieList }, Movie: { screen: Movie }, }, { navigationOptions: { headerTintColor: Colors.accent, headerStyle: Styles.header, } }) const App = createAppContainer(AppNavigator) app/App.js

Slide 106

Slide 106 text

Let’s do it const AppNavigator = createStackNavigator({ Home: { screen: MovieList }, Movie: { screen: Movie }, }, { navigationOptions: { headerTintColor: Colors.accent, headerStyle: Styles.header, } }) const App = createAppContainer(AppNavigator) app/App.js export default class MovieList extends Component { static navigationOptions = { title: 'Movies', } //… app/components/MovieList.js

Slide 107

Slide 107 text

Let’s do it const AppNavigator = createStackNavigator({ Home: { screen: MovieList }, Movie: { screen: Movie }, }, { navigationOptions: { headerTintColor: Colors.accent, headerStyle: Styles.header, } }) const App = createAppContainer(AppNavigator) app/App.js export default class MovieList extends Component { static navigationOptions = { title: 'Movies', } //… app/components/MovieList.js } keyExtractor={item => item.name} renderItem={({item}) => navigate('Movie', {name: item.name})} > } /> In render()

Slide 108

Slide 108 text

Let’s do it const AppNavigator = createStackNavigator({ Home: { screen: MovieList }, Movie: { screen: Movie }, }, { navigationOptions: { headerTintColor: Colors.accent, headerStyle: Styles.header, } }) const App = createAppContainer(AppNavigator) app/App.js export default class MovieList extends Component { static navigationOptions = { title: 'Movies', } //… app/components/MovieList.js } keyExtractor={item => item.name} renderItem={({item}) => navigate('Movie', {name: item.name})} > } /> In render()

Slide 109

Slide 109 text

Exercise Can you make a navigation transition from Movie to app/components/Actor ? Steps: - Declare the screen in app/App.js - Use a TouchableHighlight to capture onPress in the actors list of - Provide an appropriate title in - Make the actor displayed based on props.navigation.state.params.name Optional: have a look at https://reactnavigation.org/docs/en/stack-navigator.html And tweak the navigation (Ideas: mode modal, add something to headerRight)

Slide 110

Slide 110 text

Networking

Slide 111

Slide 111 text

Networking React-native uses the Fetch API If you already know it, you are all set

Slide 112

Slide 112 text

Let’s do it componentDidMount() { return fetch(baseUrl + '/movies') .then((response) => response.json()) .then((responseJson) => { this.setState({ isLoading: false, movies: responseJson, }) }) .catch((error) => { console.error(error); }) } app/components/MovieList.js

Slide 113

Slide 113 text

Let’s do it git checkout networking yarn install yarn start-server (or npm run start-server) (To discard your changes) git reset HEAD --hard

Slide 114

Slide 114 text

Further reading https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch Docs: https://github.com/mzabriskie/axios Additional libraries:

Slide 115

Slide 115 text

Interactive

Slide 116

Slide 116 text

Our goal

Slide 117

Slide 117 text

Working with state Not specific of React Native, we just use what we know of React

Slide 118

Slide 118 text

Let’s do it git checkout interactive (To discard your changes) git reset HEAD --hard

Slide 119

Slide 119 text

Modify the native side

Slide 120

Slide 120 text

Cases where it is needed Installing packages that have a native side Making our own changes or components Installing assets, such as fonts …

Slide 121

Slide 121 text

Simple case Install this font

Slide 122

Slide 122 text

Let’s do it module.exports = { project: { ios: {}, android: {}, }, assets: ['./assets/fonts/'], }; react-native.config.js git checkout mod-native (To discard your changes) git reset HEAD --hard

Slide 123

Slide 123 text

Let’s do it module.exports = { project: { ios: {}, android: {}, }, assets: ['./assets/fonts/'], }; react-native.config.js npx react-native link git checkout mod-native (To discard your changes) git reset HEAD --hard

Slide 124

Slide 124 text

Assets linked Changes to be committed: (use "git reset HEAD <file>..." to unstage) new file: android/app/src/main/assets/fonts/OleoScript-Bold.ttf new file: android/app/src/main/assets/fonts/OleoScript-Regular.ttf modified: ios/travolta.xcodeproj/project.pbxproj modified: ios/travolta/Info.plist modified: package.json

Slide 125

Slide 125 text

Summary: What is React Native Starting a project Working with Styles Layout Lists Navigation Networking Touching the native side

Slide 126

Slide 126 text

Thanks! @vicqr [email protected]