In this 4-part introductory React Native series, we go from learning some React Native basic components and layout all the way to integrating Redux and storing camera images in the cloud. By going over some React Native core components such as View, Text, Input, StyleSheet, and FlatList, we are quickly able to scaffold out a Instargam Feed. We then setup login using React Navigation, Fetch, and create a custom API so that all users can only access the app if authenticated. Once authenticated, we use react-native-camera and allow them to upload pictures to a CDN. We then retrieve any pictures a user has created to build out their own profile page.
Key Topics Covered:
React Navigation including the new SwitchNavigator and TabNavigator
React Native Camera
Network Requests with Fetch
Image Uploading with Turbo CDN
Authentication and a custom API with Turbo and Express
Setting Up and Layouts
Project Introduction - 0:00 We briefly introduce the series as Turbo360 will begin producing more content focused on React Native, then touch on some of the high-level differences from web and native as the concepts aren’t difficult, but they will be new. This is a great time to get into mobile development with React Native.
Laying out the Layout, with Flexbox - 3:15 We begin by finding some screengrabs to begin working with. We look quickly at the overall layout, the nav/tab bar and the header are components we won’t get to in this first video, we’ll work with those when we introduce the navigation library. Good news if you’ve used Flexbox before, as React Native development uses it for the layout. The Aspect Ratios between different mobile devices vary widely and will always be changing so Flexbox provides some uniformity and is actually one of the advantages of React Native over Swift or Objective C.
Install Turbo - 8:15 In order to keep our bundle size down, you want to serve as many assets remotely as possible. To aid in this, we will use the Turbo360 back-end to develop and host our app. It’s free and easy to download and install this full-featured development platform built on Serverless technology. We’re putting a particular emphasis on development along Best Practices, so we’re going to upload our images onto the Turbo back-end, rather than serving them locally for purposes of expediency. We find an image and upload into our back-end so now the URL is CDN optimized.
Setup Your Environment/Create App/Directory Tree - 12:18 If you haven’t set up for React Native development, go to Ryan’s Set Up for React Native tutorial in the links. We then create our app, demonstrating both how to create from Source or via Expo, then take a look at the directory tree for a RN project. Next, we introduce the App component and the AppRegistry.registerComponent() command in the index.js file at the root. All the while, we touch on some development practices like managing terminal tabs as the init command builds our project in the Expo app. Remember, this will take extra time to process through the initial build.
Intro to Flexbox mobile - 22:00 The biggest difference you’ll notice, coming from web, is the use of percentages to portion out the layout. We also see evidence of the additional overhead involved in these mobile projects, once you’re past it, development will feel pretty familiar to web React projects, but these differences are something to get used to.
Intro to RN Components - 27:15 Our App.js file houses the scaffolded project at initialization, that’s all you’ll want to keep, so we do some basic code clean-up, leaving us with an empty container. A View component is analogous to a "div" tag in web, it’s one of the most common ones you’ll see. A Stylesheet component is exactly that. We then look at our App component’s layout, note how similar it is to a regular ReactJS web component. We’ll then take some time to quickly build out a directory tree within our /src/ directory so, down the line as we’re working, we’ve got some organization. We then look quickly at the RN docks, probably 90% of the work you’ll do will be within the same 10 or so components. We then import our components and begin our development process.
Starting Our Layout - 37:40 The image has a source parameter object that uses a uri: parameter that takes a string value; use the CDN we created earlier. We’ll then add some style to our View component. You’ll notice there are some differences from React web development, but it should all look pretty familliar.
Bar/Menu - 45:40 We’re going to put a username and a collapse nav menu above our image, with a quick reminder on spacing from the navigation library, which we’ll explore in depth later. For now, we just create a placeholder so we get a feel for the UI. We then spend some time styling the image and basic layout as you see, in real time, what some of the issues you’ll bump into with RN development. One thing we demonstrate is the .hairlineWidth property, which is one of the many mobile-specific methods you’ll want to master in RN development.
Static UI Setup - 52:40 Our purpose here will be to build out the static UI, to which we’ll add dynamic, programmable attributes. We want this to look, statically, somewhat like our end product. We add the Instagram title to the top of the screen, then style the text. We then discuss the concepts behind Flex Direction. We add margin properties to the style object and then work out the alignment of the collapse menus. We then add the userBar component, then include all the styles. Notice how we develop and position objects in the Flexbox layout. We should now have our user thumbnail, some text for the username and the little collapse menu.
Careful Closing Your Components - 1:04:30 Be careful with the self-closing components. components are like divs, but look like full React components (because they are), but they’re easy to mix up when you create self-closers and lose track as your UI gets more complex. Coming from a React web background, this syntax can feel a little awkward. This caused an error we watch Ryan troubleshoot in real-time (and an error the dev summarizing this video also made working on his app, so watch out!)
Styling/Flex Direction - 1:05:10 In real-time we’re getting a sense of the choice Ryan needs to make. We can see how much goes into each little UI change, remember, since the screen is so small, every little piece of real-estate is extremely valuable so we’re going to spend a lot of time on it, similar to how you’d approach a responsive mobile-web app. Flex Direction commands the x or y axis with the ‘row’ and ‘column’ property We note that the creation of objects in the Stylesheet component promote reusable, DRY code. Remember to enable hot reloading if you’d like to see changes reflected instantaneously.
Image Manipulation/Adding Lifecycle Methods - 1:15:04 Always pay attention to the aspect ratio of images you select, in our case, the landing page requires an aspect ratio with a higher verticle than horizontal to reflect the shape of the device we’re working on. We go back to the Turbo docs to find a parameter we can add to the query string as a quick, easy way crop our images. Our goal is for the app to recognize the window size of the device and fit the image to that size, to this end, we’ll overwrite the ComponentDidMount() lifecycle so that it finds the width of the window as soon as the component does mount and stores it in state. We then use that figure to quickly calculate the window height as a function of the width so the solution is programmable.
Break/Touchable Features in Mobile Development - 1:32:52 After a short break, we begin by discussing what’s next. We’re going to build out the Like/Share toolbar and begin by finding an appropriate heart outline icon, which fills when a user touches the screen twice. We create a config file where we’ll link to the served asset, which makes retrieving it more DRY. Also, at compile time, this solution bundles the asset into a module using CommonJS require() module syntax for optimization. We then add a styles object so those properties are packaged as well. We emphasize DRY and the need to deal with these issues consistently and strategically.
Icon Bar 1:41:45 We continue by adding an iconBar object to the styles object within the instaClone.js component, which is an ES6 Class. We briefly note that it’s important to match properties with the objects/functions/classes that will call them, which is why we’d previously created separate modules for assets which need to be reusable, so therefore must retain the properties they would need to call outside a given particular object/function/class. We then spend a bit of time adding styling to the objects in the Icon Bar, note the Trial & Error process.
Adding Touchable Functionality - 1:52:04 We add some styling to the heart icon in order to begin building out our functionality which dynamically styles objects as users interact with them. We add a boolean property called ‘liked’ to our State Constructor because, at this point, our component needs to be aware whether the user has ‘liked’ an image. We then add an event handler function that toggles the boolean to reflect changes in state which users can affect, then a ternary expression within the render function ensures that this value figures into the composition of the icon’s state going forward. We then create a Touchable Opacity object, using an imported component.
Touchable Opacity - 1:59:45 We’ve imported the Touchable Opactity component previously and now will build out the functionality, beginning by adding values to an activeOpacity property built into that component library.
Scrolling/Adding New Components - 2:06:56 We’re finally ready to start breaking our project into components, to do so we create a container and presentation directories and copy/paste text into our new components as necessary. This promotes modularity in our code, which is essential in React projects and modern development. We go on to create a PostFeed container which will contain the user timeline. As we’re building components, you’ll notice that the workflow should look familiar to building React components for any web application. We troubleshoot an issue rendering the image as expected and make corrections by adding style properties in-line.
Flat List - 2:17:31 Rendering elements on the fly causes performance issues. Flat lists apply properties using a process that’s similar to batch uploads used in many other places, allowing attributes to be available in the application as the user scrolls, which makes it appear much more responsive to user interaction. We now create the FlatList component and set up our application to render dummy post data so we can move into the next steps, which is to start rendering real data.
Navigation & Authentication
Intro to Navigation - 0:00 We begin by introducing navigation in mobile applications. Web application navigation is necessarily browser-driven because the browser, in a sense, sits between the user and the content they wish to access. Mobile/native development aspires toward an intuitive, natural (or native) feel where the user experiences the device as an extension of self. Everything about the design and workflow of a mobile app should seek to simulate, or augment the user’s sensory perception that the device is actually responding to them. Hence, finger scrolling replaces a ‘Back’ button and frees us to think of our app’s navigation from the perspective of pure user intuition. We start to consider the naviation workflow by walking through a simple example
Navigation Workflow - 14: 26 We begin by taking the code from the main instaClone.js file we’ve been working out of and exporting it into a new MainFeed component, then adjust our file references. We then create a few of the components we are going to use later in the application, building out our component tree, which facilitates efficiency in development.
Auth Workflow - 21:08 We create a Login component. We’re going to build out a structure of nested objects that will become our directory/navigation tree. As we proceed, note the ongoing thought we put in balancing decisions on user experience versus development expediency, exemplified by the decision to add in the TouchableOpacity component. We’re making this temporary change to expedite the build/test cycle, after which we might want to consider our options. We’ll then pull up the docs to see how to apply the new Switch navigator component.
Switch Navigation - 26:01 As discussed earlier in the video, the Switch Navigator is an addition to the React Navigation library. We download and install the package, then set to importing it into our components. We can then work with the props defined in that module. We then create the new components we’ll need to build out the shell of our navigation/directory tree.
Login Workflow - 38:56 We need to check credentials at login. For this we’ll import the Stack Navigator. We look at features like the back button, which should match your device type. We also look quickly at the Tab Navigator and link them conceptually to the Switch Navigator
Text Input - 45:59 We import the Text Input component which will allow us to input text so users can provide registration information which they’ll then use to match against credentials for future logins. We then drop in two text Input Fields and a Button (remember your title prop). We’re again including style objects within the component so the correct property definitions are available to the application at run-time.
Controlled Text Input Component - 57:31 Before we can transmit login or registration data through an API to the back-end of our application, we need to persist data to state as users enter it. Because there’s no way or any app to know the end state of a user’s input beforehand, we need to provision our user data storage at every incremental change in the text field. For this, we use an onChange method, which we’ll then define. We use the Object.assign method because, broadly, React ‘reacts’ to changes in state, which drives the rendering and re-rendering cycles in its component structure, the presence of new objects triggers re-rendering, while also allowing us to avoid directly modifying state. Remember to check the docs for helpful properties, like autoCorrect, etc.
Authentication - 1:08:52 Authentication requires a back-end service to store data against which we’ll compare client data from the device (or browser, since the logic is exactly the same in mobile as it is in web). For that we’re going to use Turbo360’s out-of-the-box back-end solution where we’ve previously used to build a CDN for remote assets, like images.
Turbo360 User Management - 1:16:47 We consult the Turbo docs once more and, from code provided in the docs, we build a POST route to handle the signup endpoint and test. We then link our app and deploy onto the Turbo staging server, verifying that the connection is true. Now, we’ve got a back-end that’s ready to store data that we’ll use to compare to login information provided from the client. We’ll then create a module, into which we’ll input constants, like URL’s, whose definitions we want centralized, but for distributed use.
Enable HTTPS - 1:36:26 By default X-Code no longer allows HTTP requests. Fortunately, Turbo produces free HTTPS certificates out-of-the-box so we can adapt with minimal adjustment to our configuration. We then rebuild the project from our terminal window so we can get back to building our Authentication workflow.
Signup/Register Route - 1:47:00 We resume the building of our Signup POST route. Here, we troubleshoot by opening up the debugger where we can see the data that is transmitting. Now, we need to build a callback that will provide the user response we’ll need, this should include the UserID. We’ll then consult the React Navigation docs and take the response object they’ve defined and link it into our route’s promise chain. Once again, we’re demonstrating the trial-and-error process involved in developing apps in real-time. We’ll now build a response-handler in the promise chain that will proceed after receiving a confirmation: “success” from the back-end authentication flow. Likewise, we’ll also build an error-handler for rejected requests. We can now view our user data stored in the Turbo back-end.
Login Route - 2:00:29 Conveniently, also in the Turbo docs, we find code defining a login route which we can paste into our code and use after some light modification. We then save our changes, go back to the terminal and run the ‘turbo deploy’ command to redeploy our app to the Turbo360 staging server. We’re then taking that code and pasting back into the Login component. Generally, this would be a good use case for a single component with more dynamic attributes which would handle both workflows, but, in order to save time, we will do it this way. Here again, we always want to keep in mind that, during the course of an incremental development process, we should understand what we expect our app to be able to do so we can test and find all the bugs we should at the correct point in time. Ryan demonstrates this by testing the signup and login workflows for both success and failure, which uncovers small mistakes whose fixes are obvious now, but might appear to originate from a more opaque source in the future. We finish by troubleshooting the workflow. We then review the navigation layers we’ve created.
Introduction - 0:00 We begin by reviewing what we have accomplished in the previous parts of this tutorial. We set up the base layout of the application, learned about styling, used React navigation, and learned about HTTP requests an authentication. In this part of the tutorial, we are going to install the React Native camera and learn how to send our pictures off to a server.
Steps - 1:44 We discuss the workflow of this part of the tutorial. First, the user takes a picture with the React Native camera. Then, we send the picture to a server. Then, the server, which will be Turbo, receives the picture. The server saves the picture to a CDN. Then, we get a callback with the picture’s URL. Then, we relate this URL to the user using the Turbo API.
React Native Camera - 5:07 We discuss the features of the React Native Camera and explain how it works for Expo and Android users. We run the installation command for react-native-camera, and link it to our project without requiring manual installation. We change some of the key-value pairs to control what our users see when the application requests camera access. We also add permissions to our Android version of the application.
Taking a Picture - 14:40 We open our Camera component and paste in code from the React Native Camera documentation. Then, we show how to differentiate between the front and back cameras, and test to make sure the camera is working. We log our data, and find the link to the picture we just took.
Picture Route - 21:21 Using the API we created in the previous parts of this tutorial, we create a POST route for receiving pictures from our front end.
Sending User IDs to the Back End - 24:56 We run our Turbo project locally and use the fetch library to post our data to the back end. We then take a step back and store the user’s ID by passing it as a parameter using our React Native navigation. We do this because we want to link the user to the picture being taken. Note that while outside the scope of this tutorial, Redux adds a simpler way to keep track of this type of data. Now we take a picture and ensure that we see the user ID on the back end.
Sending Data to the CDN - 44:57 Since we know our user ID is being passed properly to the back end, we switch our strategy and send our picture and user ID directly to the Turbo CDN. We import the Turbo class and instantiate it with our site ID. We use the uploadFile function and pass it a URI, file name, and file type. We receive a URL in the callback from this operation, and this URL points to our image which is now stored in the Turbo CDN.
Persisting to the Datastore We use the fetch library to send our URL to our back end route. Logging the body of the request shows that we are properly passing the URL. We create a photo object which contains the photo’s URL and the user’s ID. Then, we persist the object to the Turbo Datastore. We check the Datastore and see that the photo entity has been created and contains our photos.
Profile Page Initial Load - 1:03:52 When our profile component initially mounts, it will load all of the pictures. When a new picture is taken, we want it to automatically be added to the list of pictures in our profile component. Since it only mounts once, we need to manually add a new picture to this component each time one is taken. For the initial load, we use fetch to add a call to our Turbo API to retrieve photos posted by the current user from the Datastore. For now, we hardcode our user ID in our Profile component. In the next part of the tutorial, we are going to add Redux to do this dynamically. We create our back end route which will get all of our photos, and upon success we return the photo data we retrieved.
Showing Profile Pictures on Initial Load - 1:31:32 When we get a response from the back end, we set the state so it maintains our pictures relevant to the profile. Then we render the URLs on the front end to ensure we are retrieving them properly. Next, we render the images for each of our URLs and add some styling to make them look like proper thumbnails, including automatically resizing the images to create rows of three. This is done by using Turbo’s built-in image resizing functionality.
Automatically Adding New Pictures - 1:55:30 When new pictures are taken, we want to automatically include them on the profile page without reloading all photos from the database. When a photo is taken, we store all of the returned data using our navigation. Then, we add a listener to keep track of the new photos. If a new photo is found, we push it to the existing picture array and update our state to contain the new photo.
Recap - 2:12:05 We finish of this part of the tutorial by doing a quick recap. When a picture is taken, it gets uploaded directly to the Turbo CDN. Then we get a callback in our camera component and make a request to our API route with the data from this callback. Then, our route ties the photo to the user. When we receive a response from the datastore, we add the new picture to our profile screen using React Native navigation. Using this flow, we don’t have to refetch all of the photos each time a new one is taken. In the next part of the tutorial, we'll clean up our state management by adding Redux, and add more styling and functionality to finish up the entire application.
In the final part of this 4 part intro course to React Native, we go back to our video one roots and style up the profile page. We then setup Redux to handle some of our state management so we do not need to rely upon React Navigation to share data between components. Finally, we adjust our API call so our user can receive all their photos on log in and access them from their Redux store.