Book Image

React Native Cookbook

By : Crysfel Villa, Stan Bershadskiy
Book Image

React Native Cookbook

By: Crysfel Villa, Stan Bershadskiy

Overview of this book

<p>React has taken the web development world by storm, and it is only natural that the unique architecture and its ecosystem of third-party support be applied to native application development. This book will take you through the basics of React Native development all the way through to some more advanced components.</p> <p>This book covers topics in React Native ranging from adding basic UI components to successfully deploying for multiple target platforms. The book follows a top-down approach beginning with building rich user interfaces. These UIs will be created with both built-in and custom components that you will create, style, and animate.</p> <p>You will then learn about different strategies for working with data, including leveraging the popular Redux library and optimizing the performance of the application. Then, you will step further into exposing native device functionality. Finally, we will discuss how to put your application into production and maintain its reliability.</p>
Table of Contents (19 chapters)
React Native Cookbook
Credits
Foreword
About the Authors
About the Reviewer
www.PacktPub.com
Customer Feedback
Preface

Setting up a navigator


One of the most popular features in React Native is the navigator. This component allows us to add or remove views easily. When we add a new view, the navigator will transition with a nice animation to the new view, and when removing the latest view, the navigator will go to the previous view with a nice animation as well.

Getting ready

Before we start working on this recipe, we need to create a new app using the React Native CLI--let's name it UsingNavigator. We are going to create a simple music app similar to Spotify. At the home page, we will display a list of songs, and we are going to display the details, whenever any of these songs are tapped.

For this recipe, we are going to use three classes, so let's create an src folder where all our code will be. Then we'll create three files, MainApp.js, Home.js, and Detail.js.

How to do it...

  1. This time, we are going to start by updating the index.ios.js and index.android.js files. We are going to require the MainApp class, which, for now, is empty, because we want to test our app while adding the new features:

           import React, { Component } from 'react'; 
           import { AppRegistry } from 'react-native'; 
           import MainApp from './src/MainApp'; 
     
           AppRegistry.registerComponent('UsingNavigator', () => MainApp); 
    
  2. Let's create the main class. Here, we are going to import all the views that we want to display in the navigator, as well as the dependencies for this component:

           import React, { Component } from 'react'; 
           import { 
             StyleSheet, 
             Navigator, 
           } from 'react-native'; 
           import Home from './Home'; 
           import Detail from './Detail'; 
    
  3. Once we have the dependencies, we need to create the class. Inside the render method, we will only define the Navigator. This component will be responsible for loading the correct scene based on the route. Using the configureScene property, we can set the default animation for all transitions. For this example, we will animate the new view from the bottom to the top of the screen, but we can also define an animation from left to right, or any other direction. I recommend you go to the documentation to see all the available options that we have:

           class MainApp extends Component { 
     
             renderScene(route, navigator) { 
               // Defined on step 4 
             } 
     
             render() { 
     
               return ( 
                 <Navigator 
                   ref="navigator" 
                   style={styles.container} 
                   configureScene={(route) =>       
                   Navigator.SceneConfigs.FloatFromBottom} 
                   initialRoute={{}} 
                   renderScene={this.renderScene} 
                 /> 
               ); 
             } 
           } 
     
           const styles = StyleSheet.create({ 
             container: { 
               flex: 1, 
             }, 
           }); 
           export default MainApp; 
    
  4. The renderScene method will get executed every time we push or pop a scene. Here, we need to decide which view we will render by returning the component based on the route. We could have as many views as needed. In this case, we only have the Detail and the Home:

              renderScene(route, navigator) { 
               if (route.song) { 
                 return ( 
                   <Detail song={route.song} navigator={navigator} /> 
                 ); 
               } 
     
               return <Home navigator={navigator} />; 
             } 
    
  5. We are done with the main class. Now we can work on the Home component. We will start by importing all the dependencies for this class:

           import React, { Component } from 'react'; 
           import { 
             StyleSheet, 
             View, 
             Image, 
             Text, 
             ScrollView, 
             TouchableHighlight, 
           } from 'react-native'; 
    
  6. We are going to define the data for the songs in the state of the component. We will have several sections with a list of songs, for example, 'Just for you', 'Recently played', and 'Popular music'. For now, I will define the structure of one section only, because I don't want to clutter this book, but you can duplicate the same structure of data to create more sections. Here's what the class looks like with the data:

            class Home extends Component { 
             state = { 
               forYou: { // Please duplicate this data 
                 title: 'Just for you', 
                 root: 
                 'https://s3.amazonaws.com/crysfel/public/book/01/07', 
                 songs: [ 
                   {title:'Some nice song', image: '1.jpg'}, 
                   {title:'One more nice song', image: '2.jpg'}, 
                   {title:'Here is one more song', image: '3.jpg'}, 
                   {title:'Really nice song', image: '4.jpg'}, 
                   {title:'I love this song', image: '5.jpg'}, 
                   {title:'This is a song', image: '6.jpg'}, 
                 ], 
               }, 
             }; 
     
             onSelectSong(song) { 
               // Defined on step 10 
             } 
     
             renderSong(section, song, index){ 
               // Defined on step 9 
             } 
     
             renderSection(options) { 
              // Defined on step 8 
            } 
     
            render() { 
              // Defined on step 7 
            } 
          } 
          export default Home;
  7. In the render method, we are going to define a title bar and three sections. Remember to duplicate the data on the state in order for this to work correctly:

            render() { 
             const { 
               forYou, 
               played,  // Name of the duplicated data 
               popular, // Name of the duplicated data 
             } = this.state; 
     
             return ( 
               <View style={styles.container}> 
                 <Text style={styles.title}>Home</Text> 
                 {this.renderSection(forYou)} 
                 {this.renderSection(played)} 
                 {this.renderSection(popular)} 
               </View> 
             ); 
           } 
    
  8. For each section, we are calling the renderSection method, which will render the title of the section and the list of songs in this group. We are going to use the ScrollView component to allow the user to scroll through the list horizontally. To render the songs, we need to loop the songs array of each section. We can do this by using the map method and an arrow function:

            renderSection(options) { 
             return ( 
               <View style={styles.section}> 
                 <Text  
                   style={styles.sectionTitle} 
                 > 
                   {options.title.toUpperCase()} 
                 </Text> 
                 <ScrollView 
                   horizontal 
                   showsHorizontalScrollIndicator={false}> 
                   { 
                    options.songs.map( 
                      (song, index) =>
                      this.renderSong(options, song, index) 
                    ) 
                   } 
                 </ScrollView> 
               </View> 
             ); 
           } 
    
  9. Now we need to render the song. We will display the image and the title for each song. The image is hosted on Amazon S3. We are going to use the TouchableHighlight component because we want to detect the press event to show the detail of each song. It's important to mention that this component only accepts a single child; therefore, we need to use a wrapper to group the image and the title; otherwise, we will get errors:

            renderSong(section, song, index){ 
             return ( 
               <TouchableHighlight 
                 onPress={() => this.onSelectSong(song)} 
                 style={styles.song} key={index} 
               > 
                 <View> 
                   <Image 
                     source={{uri:`${section.root}/${song.image}`}} 
                     style={styles.image} 
                   /> 
                   <Text style={styles.songTitle}>{song.title}</Text> 
                 </View> 
               </TouchableHighlight> 
             ); 
           } 
    
  10. In the previous step, we are calling the onSelectSong method when the user presses the button. This function is the one that will run the transition on the navigator. All we need to do is call the push method on the navigator and pass the details object. The renderScene method will check if the song object is there, and will show the scene that we need:

           onSelectSong(song) { 
            this.props.navigator.push({song}); 
           }  
    
  11. We are done with JSX. Now we need to add some styles to make this look pretty. Let's start by adding styles to the title bar and the main container:

            const styles = StyleSheet.create({ 
             container: { 
               flex: 1, 
               backgroundColor: '#0c1b1a', 
             }, 
             title: { 
               backgroundColor: '#37b298', 
               color: '#fff', 
               padding: 10, 
               paddingTop: 30, 
               textAlign: 'center', 
               fontWeight: 'bold', 
               fontSize: 18, 
             }, 
           }); 
    

  12. Next, let's style the sectionTitle, the image, and the songTitle, something really simple--just adding some padding, color, and setting the width and height for each image:

           section: { 
             padding: 10, 
           }, 
           sectionTitle: { 
             color: '#fff', 
             fontWeight: '200', 
             paddingBottom: 10, 
           }, 
           song: { 
             backgroundColor: '#081412', 
             marginRight: 10, 
           }, 
           image: { 
              width: 120, 
              height: 120, 
            }, 
            songTitle: { 
              color: '#f1f1f1', 
              fontWeight: '200', 
              fontSize: 12, 
              flex: 1, 
              padding: 5, 
              width: 100, 
            } 
    

  13. It's looking amazing! We can now scroll the list of each section horizontally. If we tap on any of the songs, we will get an error because we haven't defined the detail view. Let's start by importing the dependencies on the Detail.js file. We are going to import the PropTypes object. This object allows us to define the types of property our component will support. This step is very important because we can receive data from other components by using properties. In this example, we will receive the data from the home component, which will be an object with the song's data:

            import React, { Component, PropTypes } from 'react'; 
            import { 
              StyleSheet, 
              View, 
              Image, 
              Text, 
            } from 'react-native'; 
     
            const { object } = PropTypes; 
            const root =
            'https://s3.amazonaws.com/crysfel/public/book/01/07'; 
    
  14. The class is a lot simpler. We are only defining the image and title from the song that we will receive in the properties; then we will display a list of other songs from the same artist. To make things a lot simpler, this list will be a hardcoded list of Text elements:

           class Detail extends Component { 
             static propTypes = { 
               song: object, 
               navigator: object, 
             }; 
           
             render() { 
               const { song } = this.props; 
     
               return ( 
                 <View style={styles.container}> 
                   <View style={styles.info}> 
                     <Image 
                       source={{uri: `${root}/${song.image}`}} 
                       style={styles.image} 
                     /> 
                     <Text style={styles.title}>{song.title}</Text> 
                     <View style={styles.playContainer}> 
                       <Text style={styles.play}>Play song</Text> 
                     </View> 
                   </View> 
                   <Text style={styles.other}>01 - One more song</Text> 
                   <Text style={styles.other}>02 - Other song here</Text> 
                   <Text style={styles.other}>
                   03 - This is the last song</Text> 
                   <Text style={styles.other}>
                   04 - Maybe this is the last song?</Text> 
                   <Text style={styles.other}>
                   05 - Why not one more song?</Text> 
                   <Text style={styles.other}>
                   06 - Finally this is the last song</Text> 
                 </View> 
               ); 
             } 
           } 
     
           export default Detail; 
    
  15. Now let's style this component. We are going to display the image as a circle, and then we will display the title of the song we are receiving:

           const styles = StyleSheet.create({ 
             container: { 
               backgroundColor: '#0c1b1a', 
               flex: 1, 
             }, 
             info: { 
               padding: 50, 
               alignItems: 'center', 
             }, 
             image: { 
               width: 150, 
               height: 150, 
               borderRadius: 75, 
             }, 
             title: { 
               fontSize: 20, 
               fontWeight: '200', 
               color: '#fff', 
               marginTop: 23, 
             }, 
           }); 
    
  16. Finally, we will display the list of additional songs and the play button, which is really simple:

           playContainer: { 
             backgroundColor: '#37b298', 
             padding: 10, 
             paddingRight: 50, 
             paddingLeft: 50, 
             borderRadius: 10, 
             marginTop: 20, 
           }, 
           play: { 
             color: '#fff', 
           }, 
           other: { 
             color: '#f1f1f1', 
             padding: 10, 
             marginRight: 10, 
             marginLeft: 10, 
             backgroundColor: '#081412', 
             marginBottom: 1, 
           }, 
    
  17. At this point, we should have something similar to the following screenshot:

There's more...

The navigator is a very important component. Almost every application requires some sort of navigator to add some nice transitions. In this recipe, we covered the cross-platform navigator, which works on iOS and Android. This is because everything is on the JavaScript side. If we require something native, we should take a look at NavigatorIOS and ViewPagerAndroid.