Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

React Native Workshop - React Alicante

1,059 views

Published on

Supporting slides of my introductory workshop about React Native in React Alicante 2017.

Source code & Exercises: https://github.com/Limenius/workshop-react-native

Published in: Software
  • ➤➤ 3 Reasons Why You Shouldn't take Pills for ED (important)  http://ishbv.com/rockhardx/pdf♣♣ 10 Easy Ways to Improve Your Performance in Bed... ♣♣♣ https://tinyurl.com/rockhardxxx
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

React Native Workshop - React Alicante

  1. 1. September 2017 Introduction to React Native Nacho Martín
  2. 2. Nacho Martin I write code at Limenius. We build tailor-made projects, and provide consultancy and formation. We are very happy with React and React Native.
  3. 3. Roadmap: What is React Native Starting a project Working with Styles Layout Lists Navigation Networking Touching the native side
  4. 4. What is React Native?
  5. 5. Fundamental premise of React Give me a state and a render() method that depends on it and forget about how and when to render.*
  6. 6. Fundamental premise of React Give me a state and a render() method that depends on it and forget about how and when to render.* * Unless you want more control.
  7. 7. render() { return ( <div className="App"> <button onClick={this.tick}>Click me!</button> <span>Clicks: {this.state.count}</span> </div> ) }
  8. 8. render() { return ( <div className="App"> <button onClick={this.tick}>Click me!</button> <span>Clicks: {this.state.count}</span> </div> ) } render() { return ( <View style={…}> <Button onPress={this.tick}>Click me!</Button> <Text>Clicks: {this.state.count}</Text> </View> ) }
  9. 9. render() { return ( <div className="App"> <button onClick={this.tick}>Click me!</button> <span>Clicks: {this.state.count}</span> </div> ) } render() { return ( <View style={…}> <Button onPress={this.tick}>Click me!</Button> <Text>Clicks: {this.state.count}</Text> </View> ) }
  10. 10. render() { return ( <div className="App"> <button onClick={this.tick}>Click me!</button> <span>Clicks: {this.state.count}</span> </div> ) } render() { return ( <View style={…}> <Button onPress={this.tick}>Click me!</Button> <Text>Clicks: {this.state.count}</Text> </View> ) } React Native
  11. 11. How is this possible Reconciliation Determines what parts of the tree have changed
  12. 12. How is this possible Reconciliation Determines what parts of the tree have changed Rendering Actually updates the app
  13. 13. How is this possible Reconciliation Determines what parts of the tree have changed Rendering Actually updates the app We can have several renderers
  14. 14. React targets Main react-dom react-native Web iOS android
  15. 15. React targets Main react-dom react-native Web iOS android But also
  16. 16. React targets Main react-dom react-native Web iOS android But also react-art  react-canvas react-three ReactLibertyreact-worker-dom
  17. 17. React targets Main react-dom react-native Web iOS android But also react-art  react-canvas react-three ReactLibertyreact-worker-dom react-konsul raxreact-native  react-blessedreact-tvml
  18. 18. React targets Main react-dom react-native Web iOS android But also react-art  react-canvas react-three ReactLibertyreact-worker-dom react-konsul raxreact-native  react-blessedreact-tvml React-GLreact-vr  react-hardware react-fs-renderer react-x11
  19. 19. React targets Main react-dom react-native Web iOS android But also react-art  react-canvas react-three ReactLibertyreact-worker-dom react-konsul raxreact-native  react-blessedreact-tvml React-GLreact-vr  react-hardware react-fs-renderer react-x11 redocx react-titanium  React-Gibbon react-pdf  react-test-renderer
  20. 20. React targets Main react-dom react-native Web iOS android But also react-art  react-canvas react-three ReactLibertyreact-worker-dom react-konsul raxreact-native  react-blessedreact-tvml React-GLreact-vr  react-hardware react-fs-renderer react-x11 redocx react-titanium  React-Gibbon react-pdf  react-test-renderer ink  react-sketchapp 
  21. 21. React blessed
  22. 22. React blessed
  23. 23. React Sketch.app
  24. 24. React VR Demo
  25. 25. How Native is React Native? JS Thread Business logic & Description of what components to render
  26. 26. How Native is React Native? JS Thread Main Thread UI manipulation with native components Business logic & Description of what components to render
  27. 27. How Native is React Native? JS Thread Main Thread UI manipulation with native components Business logic & Description of what components to render Bridge
  28. 28. How much code can we reuse? Tip: if you develop in one platform, try it in the other from time to time 70%? 80%? 90%?
  29. 29. How to start a project
  30. 30. Option 1: create-react-native-app $ npm install -g create-react-native-app $ create-react-native-app AwesomeProject
  31. 31. Option 1: create-react-native-app 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
  32. 32. Option 2: react-native init $ npm install -g react-native-cli $ react-native init AwesomeProject
  33. 33. Option 2: react-native init Complete project with native code More control Needed to use things like CodePush Doesn’t need external tools to publish to the store
  34. 34. Getting our hands dirty
  35. 35. git clone https://github.com/Limenius/workshop-react-native.git You are supposed to have done this 🙏 And then yarn install
  36. 36. git checkout dirtyhands react-native run-ios And then Or react-native run-android
  37. 37. git checkout dirtyhands react-native run-ios And then Or react-native run-android
  38. 38. Debug tools Cmd + d (Cmd + r)
  39. 39. Play around Open app/App.js with an editor <Text style={styles.welcome}>Hi there!</Text>Change the text in Try nesting <Text> <Text style={styles.welcome}>Hi there!</Text> Amigo </Text> 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
  40. 40. Familiarize with errors What happens if we… remove a closing tag (</View>) <View style={styles.container}> Hi there! </View> put text not wrapped in <Text/> try to comment a JSX line with // return ( <View style={styles.container}> <Text style={styles.welcome}>Hi there!</Text> </View> <View/> ) have two root elements use wrong properties for styles ( rename flex -> flexo ) remove the words export default
  41. 41. Basic components
  42. 42. git checkout elements git reset HEAD --hard (To discard your changes)
  43. 43. Exercise: Play with the basic components app/App.js
  44. 44. Exercise: Build new components Can you build a new component combining others? Ideas: Image with footer (<Text/>), 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
  45. 45. Style 💅
  46. 46. No CSS. Everything is JS <View style={{ borderLeftColor: Colors.accent, borderLeftWidth: 9, backgroundColor: Colors.backgroundSection, padding: 18, paddingVertical: 9, }}> No class No dimensions in pixels No things like padding: 19 9 3 1 camelCased Use constants
  47. 47. StyleSheet <View style={Styles.headline}> const Styles = StyleSheet.create({ headline: { borderLeftColor: Colors.accent, borderLeftWidth: 9, backgroundColor: Colors.backgroundSection, paddingLeft: 18, paddingRight: 18, paddingTop: 9, paddingBottom: 9, }, })
  48. 48. Combination <View style={[Styles.headline, {backgroundColor: 'red'}]}> const Styles = StyleSheet.create({ headline: { borderLeftColor: Colors.accent, borderLeftWidth: 9, paddingLeft: 18, paddingRight: 18, paddingTop: 9, paddingBottom: 9, }, })
  49. 49. git checkout styles (To discard your changes) git reset HEAD --hard
  50. 50. We want to do this
  51. 51. Our first goal is to get this (We will practice layouts in the next section)
  52. 52. 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
  53. 53. Exercise 1 84x84 Colors.text, bold Container has: border at bottom size 1, Colors.subtleAccent and background is 'white' components/ListItemActor.js
  54. 54. 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 Pro exercise:Think how would you add support for themes
  55. 55. Dimensions import { Dimensions, } from 'react-native' const windowSize = Dimensions.get('window') mainImage: { height: windowSize.height /3, width: undefined }, components/MovieHeader.js
  56. 56. 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
  57. 57. 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
  58. 58. Further reading https://www.okgrow.com/posts/react-native-styling-tips https://madebymany.com/stories/a-year-of-react-native-styling-part-1 https://medium.com/robin-powered/introducing-glamorous-for-react-native-1b8365e7f33f https://github.com/styled-components/styled-components Explore libraries to do CSS in JS
  59. 59. Layouts
  60. 60. This is flexbox realm flexDirection justifyContent alignItems alignSelf flex alignContent flexBasis flexGrow flexShrink flexWrap
  61. 61. This is flexbox realm flexDirection justifyContent alignItems alignSelf flex alignContent flexBasis flexGrow flexShrink flexWrap flexDirection: ‘column' flexDirection: ‘row’ (Default)
  62. 62. This is flexbox realm flexDirection justifyContent alignItems alignSelf flex alignContent flexBasis flexGrow flexShrink flexWrap flexDirection: ‘column' flexDirection: ‘row’ (Default) main direction crossdirection
  63. 63. This is flexbox realm flexDirection justifyContent alignItems alignSelf flex alignContent flexBasis flexGrow flexShrink flexWrap flexDirection: ‘column' flexDirection: ‘row’ (Default) main direction crossdirection cross direction maindirection
  64. 64. 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’
  65. 65. 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’
  66. 66. This is flexbox realm flexDirection justifyContent alignItems alignSelf flex alignContent flexBasis flexGrow flexShrink flexWrap flexDirection: ‘row’ ‘baseline’
  67. 67. This is flexbox realm flexDirection justifyContent alignItems alignSelf flex alignContent flexBasis flexGrow flexShrink flexWrap flexDirection: ‘column’ alignSelf: ’end’
  68. 68. This is flexbox realm flexDirection justifyContent alignItems alignSelf flex alignContent flexBasis flexGrow flexShrink flexWrap flex: 1 flex: 0 flex: 0
  69. 69. This is flexbox realm flexDirection justifyContent alignItems alignSelf flex alignContent flexBasis flexGrow flexShrink flexWrap flex: 5 flex: 2 flex: 3
  70. 70. This is flexbox realm flexDirection justifyContent alignItems alignSelf flex alignContent flexBasis flexGrow flexShrink flexWrap flex: 0.5 flex: 0.2 flex: 0.3
  71. 71. This is flexbox realm flexDirection justifyContent alignItems alignSelf flex alignContent flexBasis flexGrow flexShrink flexWrap flex: 25 flex: 10 flex: 15
  72. 72. git checkout layout (To discard your changes) git reset HEAD --hard
  73. 73. Our goal
  74. 74. app/components/MovieHeader.js
  75. 75. app/components/MovieHeader.js
  76. 76. 18 Exercise 1 app/components/ListItemActor.js
  77. 77. 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
  78. 78. Further reading https://facebook.github.io/yoga/docs/getting-started/ Docs: https://github.com/jondot/ReactNativeKatas Very good practice:
  79. 79. Lists
  80. 80. Lists are important in mobile
  81. 81. 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 ( <View> <MovieHeader movie={this.state.movie}/> { this.state.movie.actors.map(actor => ( <ListItem key={actor} name={actor} image={actors[actor].image}/> ))} </View> ) } } app/components/Movie.js
  82. 82. 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 ( <View> <MovieHeader movie={this.state.movie}/> { this.state.movie.actors.map(actor => ( <ListItem key={actor} name={actor} image={actors[actor].image}/> ))} </View> ) } } Important to help the reconciler do its work app/components/Movie.js
  83. 83. Exercise git checkout lists Can you build a list of movies in app/components/MovieList.js ? (To discard your changes) git reset HEAD --hard
  84. 84. 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 • Better Flow typing.
  85. 85. FlatList render() { return ( <View> <MovieHeader movie={this.state.movie}/> <FlatList data={this.state.movie.actors} renderItem={({item}) => <ListItem name={item} image={this.state.actors[item].image}/> } /> </View> ) } app/components/Movie.js
  86. 86. FlatList
  87. 87. FlatList What about the keys?
  88. 88. FlatList What about the keys? <FlatList data={this.state.movie.actors} keyExtractor={item => item} renderItem={({item}) => <ListItem name={item} image={this.state.actors[item].image}/> } />
  89. 89. FlatList What about the keys? <FlatList data={this.state.movie.actors} keyExtractor={item => item} renderItem={({item}) => <ListItem name={item} image={this.state.actors[item].image}/> } />
  90. 90. FlatList Scrolleable area <FlatList data={this.state.movie.actors} keyExtractor={item => item} renderItem={({item}) => <ListItem name={item} image={this.state.actors[item].image}/> } /> <MovieHeader movie={this.state.movie}/>
  91. 91. FlatList Desired scrolleable area
  92. 92. FlatList Desired scrolleable area <FlatList data={this.state.movie.actors} ListHeaderComponent={<MovieHeader movie={this.state.movie}/>} keyExtractor={item => item} renderItem={({item}) => <ListItem name={item} image={this.state.actors[item].image}/> } />
  93. 93. FlatList Desired scrolleable area <FlatList data={this.state.movie.actors} ListHeaderComponent={<MovieHeader movie={this.state.movie}/>} keyExtractor={item => item} renderItem={({item}) => <ListItem name={item} image={this.state.actors[item].image}/> } />
  94. 94. 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)
  95. 95. 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
  96. 96. Navigation
  97. 97. Navigation
  98. 98. react-navigation
  99. 99. Several options StackNavigator TabNavigator DrawerNavigator Or combine them
  100. 100. Several options StackNavigator TabNavigator DrawerNavigator Or combine them
  101. 101. Several options StackNavigator TabNavigator DrawerNavigator Or combine them
  102. 102. Several options StackNavigator TabNavigator DrawerNavigator Or combine them
  103. 103. Let’s do it git checkout navigation (To discard your changes) git reset HEAD --hard
  104. 104. Let’s do it const App = StackNavigator({ Home: { screen: MovieList }, Movie: { screen: Movie }, }, { navigationOptions: { headerTintColor: Colors.accent, headerStyle: Styles.header, } }) app/App.js
  105. 105. Let’s do it const App = StackNavigator({ Home: { screen: MovieList }, Movie: { screen: Movie }, }, { navigationOptions: { headerTintColor: Colors.accent, headerStyle: Styles.header, } }) app/App.js export default class MovieList extends Component { static navigationOptions = { title: 'Movies', } //… app/components/MovieList.js
  106. 106. Let’s do it const App = StackNavigator({ Home: { screen: MovieList }, Movie: { screen: Movie }, }, { navigationOptions: { headerTintColor: Colors.accent, headerStyle: Styles.header, } }) app/App.js export default class MovieList extends Component { static navigationOptions = { title: 'Movies', } //… app/components/MovieList.js <FlatList data={this.state.movies} ListHeaderComponent={<MainHeader/>} keyExtractor={item => item.name} renderItem={({item}) => <TouchableHighlight underlayColor={Colors.subtleAccent} activeOpacity={0.5} onPress={() => navigate('Movie', {name: item.name})} > <View> <ListItem name={item.name} image={item.image}/> </View> </TouchableHighlight> } /> In render()
  107. 107. Let’s do it const App = StackNavigator({ Home: { screen: MovieList }, Movie: { screen: Movie }, }, { navigationOptions: { headerTintColor: Colors.accent, headerStyle: Styles.header, } }) app/App.js export default class MovieList extends Component { static navigationOptions = { title: 'Movies', } //… app/components/MovieList.js <FlatList data={this.state.movies} ListHeaderComponent={<MainHeader/>} keyExtractor={item => item.name} renderItem={({item}) => <TouchableHighlight underlayColor={Colors.subtleAccent} activeOpacity={0.5} onPress={() => navigate('Movie', {name: item.name})} > <View> <ListItem name={item.name} image={item.image}/> </View> </TouchableHighlight> } /> In render()
  108. 108. 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 <Movie/> - Provide an appropriate title in <Actor/> - Make the actor displayed based on props.navigation.state.params.name Optional: have a look at https://reactnavigation.org/docs/navigators/stack#StackNavigatorConfig And tweak the navigation (Ideas: mode modal, add something to headerRight)
  109. 109. Networking
  110. 110. Networking React-native uses the Fetch API If you already know it, you are all set 🎉 
  111. 111. 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
  112. 112. Let’s do it git checkout networking yarn start-server (To discard your changes) git reset HEAD --hard
  113. 113. Further reading https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch Docs: https://github.com/mzabriskie/axios Additional libraries:
  114. 114. Interactive
  115. 115. Our goal
  116. 116. Working with state Not specific of React Native, we just use what we know of React 
  117. 117. Let’s do it git checkout interactive (To discard your changes) git reset HEAD --hard
  118. 118. Modify the native side
  119. 119. Cases where it is needed Installing packages that have a native side Making our own changes or components Installing assets, such as fonts …
  120. 120. Simple case Install this font
  121. 121. Let’s do it "rnpm": { "assets": ["./assets/fonts/"] } package.json git checkout mod-native (To discard your changes) git reset HEAD --hard
  122. 122. Let’s do it "rnpm": { "assets": ["./assets/fonts/"] } package.json react-native link git checkout mod-native (To discard your changes) git reset HEAD --hard
  123. 123. 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
  124. 124. Summary: What is React Native Starting a project Working with Styles Layout Lists Navigation Networking Touching the native side
  125. 125. Thanks! @nacmartin nacho@limenius.com

×