Upgrade to Pro — share decks privately, control downloads, hide ads and more …

React Native Workshop

React Native Workshop

React Native introductory workshop

Victoria Quirante

September 26, 2019
Tweet

More Decks by Victoria Quirante

Other Decks in Programming

Transcript

  1. 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.
  2. 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
  3. Roadmap: What is React Native Starting a project Working with

    Styles Layout Lists Navigation Networking Touching the native side
  4. Fundamental premise of React Give me a state and a

    render() method that depends on it and forget about how and when to render.
  5. 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> ) }
  6. 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> ) }
  7. 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
  8. How is this possible Reconciliation Determines what parts of the

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

    tree have changed Rendering Actually updates the app We can have several renderers
  10. React targets Main react-dom react-native Web iOS android But also

    react-art react-canvas react-three ReactLiberty react-worker-dom
  11. 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
  12. 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
  13. 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
  14. 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
  15. 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
  16. How Native is React Native? JS Thread Business logic &

    Description of what components to render
  17. How Native is React Native? JS Thread Main Thread UI

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

    manipulation with native components Business logic & Description of what components to render Bridge
  19. 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%?
  20. 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
  21. 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
  22. Play around Open app/App.js with an editor <Text style={styles.welcome}>Hi there!</Text>

    Change the text in Try nesting <View> <Text style={styles.welcome}>Hi there!</Text> Amigo </View> 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
  23. 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
  24. 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
  25. 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
  26. 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, }, })
  27. 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, }, })
  28. 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
  29. Exercise 1 84x84 Colors.text, bold Container has: border at bottom

    size 1, Colors.subtleAccent and background is 'white' components/ListItemActor.js
  30. 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
  31. Dimensions import { Dimensions, } from 'react-native' const windowSize =

    Dimensions.get('window') mainImage: { height: windowSize.height /3, width: undefined }, components/MovieHeader.js
  32. 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
  33. 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
  34. This is flexbox realm flexDirection justifyContent alignItems alignSelf flex alignContent

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

    flexBasis flexGrow flexShrink flexWrap flexDirection: ‘column' flexDirection: ‘row’ (Default) main direction cross direction
  36. 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
  37. 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’
  38. 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’
  39. This is flexbox realm flexDirection justifyContent alignItems alignSelf flex alignContent

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

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

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

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

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

    flexBasis flexGrow flexShrink flexWrap flex: 25 flex: 10 flex: 15
  45. 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
  46. 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
  47. 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
  48. Exercise git checkout lists Can you build a list of

    movies in app/components/MovieList.js ? (To discard your changes) git reset HEAD --hard
  49. 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.
  50. 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
  51. 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}/> } />
  52. 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}/> } />
  53. 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}/>
  54. 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)
  55. git checkout navigation yarn install cd ios; pod install Let’s

    do it (To discard your changes) git reset HEAD --hard If iOS
  56. 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
  57. 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
  58. 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 <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()
  59. 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 <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()
  60. 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/en/stack-navigator.html And tweak the navigation (Ideas: mode modal, add something to headerRight)
  61. 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
  62. 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
  63. Cases where it is needed Installing packages that have a

    native side Making our own changes or components Installing assets, such as fonts …
  64. 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
  65. 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
  66. 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
  67. Summary: What is React Native Starting a project Working with

    Styles Layout Lists Navigation Networking Touching the native side