In this 5-part intermediate React Native tutorial series, we spend more time learning how to deal with real data and APIs and how to integrate them into our React Native Applications by building a Telegram like messaging app. We learn how to set up a Switch Navigator to handle our authentication and user flow, along with using AsyncStorage to remember logged in users so we do not have to force our user to log in every session. We then build out a fully functioning messaging app that allows users to have conversations with other users which we create and retrieve all via an API we build ourselves. In the process we deal with some interesting issues such as handling dateTime objects so that our conversation has a normal flow and is in order, and constructing conversations based on all sent and received messages with a specific user. Key Topics covered include: React Navigation - SwitchNavigator, StackNavigator, and TabNavigator and Static methods which are not often seen in react applications but are very common in React Navigation User Authentication with Turbo and Session Management with AsyncStorage Styling our application from a Sketch Mockup Network Requests with Fetch using GET, POST, and DELETE methods Date and Time objects and moment.js Custom API Development with Node, Express, and Turbo
React Native Tutorial - Messaging App
Project Introduction - 0:00
The goal for this React Native tutorial series is having two screens that are fully functioning using a Node Express backend. We are going to decrease the overall scope of this project to be able to go over more edge cases. This application will run on both IOS and Android. To begin we set up a react native app. If you need help setting up your development environment there is a video on how to do that. The features to be included in this series are user accounts, login and signup with setting a token, sending messages, deleting messages, viewing a message, viewing all messages, infinite scrolling, and self destructing messages.
Setting up Components/File Structure - 8:35
Set up the different directories and files for the components of a React Native application. This creates the overall framework of the application. Remember you always need your bundler running in the background.
Rendering Test Messages - 14:24
We start by rendering a couple non-dynamic messages to build out the UI. The messages will be stored on Turbo in our API backend. So we connect Turbo which helps us create a simple Node Express backend for the API. We go into the routes and create some fake messages and set the route to return the messages. Then go back to the Native App set up some style and render the list of messages by creating a new component and looping over the messages. For now the messages are pasted in instead of grabbed from the backend. When running into bugs you can debug JS remotely and see what is passed to each component through console logs.
Fetching Messages From Backend 53:30
Now we want to start getting the messages from the backend. We begin by fetching messages from the state instead of the list we created. If you are on native you will have to allow HTTP requests as we are using our own URL and need an SSL cert otherwise. Use a component lifestyle method to fetch the config base url plus the API. Using a promise chain set the state to the messages you get from the response of the fetch. Import ActivityIndicator which is how you deal with asynchronous requests when you submit something it comes and leaves when it is done essentially a loading indicator.
Create Login Feature - 1:19:55
In order to create messages we will need to have a way to login. We will store tokens so you don’t have to keep logging in (single sign on). React Navigation has a new feature called SwitchNavigator that acts like a switch which we will be utilizing. React Navigation is suggested by Facebook. Our application can only have two states (logged in and logged out) to go to different screens so it is perfect for logging in. To login into the server we need a name, and password. We will send these two things off and the server will return a cookie that we need to persist with async storage. We will authenticate with Tubo directly. We create the authentication screen and link it up with Turbo. We create two functions one for logging in and one registering. We use Turbo as the central authentication authority which verifies and creates our users. We store the key returned by Turbo using async storage.
Use React Navigation - 1:55:00
Install React Navigation and create a switch navigator in the App. We want to switch between authentication and home. If the cookie is there we want to go to home and if not go to authentication.
Only Get Your Messages - 2:13:15
We go to our api and set a couple of the messages to have the toUser attribute be our ID. We set up our query string to only get the messages for our user. We persist our messages to the database on Turbo so that we can use our query string.
Styling and UI
Styling Our Messages - 0:00
Last episode we spent a lot of the time working purely on the backend so we are going to move to do some styling so that what we are working on looks nice. Using Sketch UI kit (free) we have a layout for our messages. We work with that to create a style for our messages. We change a bunch of attributes and then split the information into two flex rows following the Sketch UI. We then split the top row into two flex columns and give each half. We also add an Image in and crop the image using Turbo. You’ll see that we are unable to scroll.
Adding Scrolling - 31:00
We need to use FlatList to add the scrolling. We import it in our HomeScreen and add it to the return with taking the messages as the render item and the message state as the data. We also fix the warning where there is no key by using the key given by keyExtractor to get the id into the FlatList from item id. We also add TouchableOpacity so there is some feedback when the message is clicked. We also add the line for pressing to go to our message.
Custom StackNavigator - 40:50
We create a MessageStack in the switch with a StackNavigator so that we can navigate to either a message or the whole with the switch. Add navigation options to the MessageStack to style it. Import StatusBar to change the style of the status bar to white. Also adding a title to the navigator.
Adding The Message Page - 57:33
Create a new screen called conversation. We create the components for this conversation. We add this to our MessageStack and direct the onPress to conversation. We pass a function to navigate to the conversation with the prop.
Getting Conversation From User 1:13:00
On mount of the conversation we want to fetch the conversation with User. We make it so the navigation header title is the user. We need to get the conversation from the server so we use fetch again with a different query string. The query string will look for the messages from the opposite user that are to us. We have used this function twice across screens so we pull it into its own util folder. We have to abstract this function to do to and from user but also get our messages to that person. We download an npm package query-string to turn objects into a query string. We then change where we were fetching to use this util function. We only return the json as we want to keep the control of errors in our components. We also import our message view into the conversation as we can use the same message style/logic in the same way.
Sent Messages - 1:55:30
Create a MessageShort view and copy the style over but remove stuff that isn’t relevant such as on click and touchable opacity. We also switch conversation from using Message to MessageShort. We follow the design set forth in the UI designer in order to create a style. To flip the sent and from messages we use a dynamic row to row-reverse. This is dynamically sent by passing along a props sentMessage which is true or false based on what type of message it is. We send this prop by creating a new route “message/me/” which will return any messages with you and the person that is passed in the query param. We do this by doing two seperate queries one to user from you and one from user to you. When this is returned we set the true and false in the prop by checking if our user id is the from user if so we sent it if not they sent it.
Scrolling - 0:00
Right now we are mapping through items but we need to turn it into a flatList or make it a ScrollView. FlatList is the preferred method because ScrollView does not have good performance. So we do essentially the same thing we did with flatList in the home screen except we use a MessageShort instead of a Message and pass the sentMessage param.
Creating A Modal - 9:00
We are going to use a React Native Modal. We put the modal in the home screen and give it a view inside to see how it looks. We want to trigger out modal using a state variable. We then have a toggleCreateMessage function that toggles the state. We export the message button image from Sketch and put them into a folder called assets. We create a reference to this image in the config. We add the icon image to the header on the home screen. We increase the touchableOpacity so a human finger can touch it. We then set the navigate onPress to turn on the Modal. We also make the icon toggle off when the Modal is opened. You need to be careful with async calls as unexpected behavior may happen.
Creating Message Input - 53:37
We add a text input into a view inside the Modal this will be the user we are sending the message to. When styling if you have one attribute you can do it inline but once you get more you should drop it to the bottom to stay organized. We create an updateNewMessage function that takes a field and some text and sets the state of a newMessage object that has attributes for each field. We add the other MessageInput that will send the different field to the updateNewMessage function. We add some listeners to the keyboard so when it comes up we can grab the height and change the height of the message input.
Send or Cancel - 1:32:00
We put the message input into a column with a row that has the buttons send and cancel. We add styling to the buttons as well. We create a method cancel for deleting the message on cancel so we use set state of showCreateMessage to false and set the newMessage to nothing. We then set the on press of the cancel button to that method. We also create the send method which calls a util method called createMessages that we create in our util. This will do a POST request to our API. We then need to create the post request route on the API. We then make it so when we send we get forwarded to the conversation.
Logging In and Out
Login - 0:00
We are going to make a profile tab for logout and also build out the authentication screen. We have to delete the cookie to create the login screen so we remove it from the async storage. We use this to get back to our authenticate screen.
Setting Up Authenticate Screen - 8:20
We start by setting up our view. We also add two text inputs one for login and one for the password. We use onChangeText just like the previous video. We set up the style bringing the purple we use across the app into a config. We put the inputs at the top half of the screen in order to avoid the keyboard. We add additional labels to people know which one is username and password. If you want a challenge try to copy the AirbBNB login screen. We make a register button and a submit button. We make the register button toggle our text to change from login to a register screen or visa versa. On submit depending what ‘screen’ we are on we either use register or login. We also need to set our token on login and forward to home.
Adding Logout - 46:18
We are going to make a tab navigator which is similar to what we have been doing earlier with navigators. We create a profile screen and pull the style from the authentication screen changing a thing here or there to create a logout button. With this logout button we want to delete our userIdKey from AsyncStorage. We then want to navigate them back to the authenticate screen.
On Different Simulators - 1:04:40
Pulling out an Iphone 6 simulator we remember we hardcoding the height of the Modal. We now need to make it dynamic. So we find we can import the header, get the height there and use Header.Height to get our marginTop. We also work to improve the look by adding tab icon images.
Sorting Messages - 1:25:30
There is two ways to sort the messages, client side, and server side. We are going to do it client side because there are a lot of projects where you won’t always get the data in a way you want it. We make a util method that takes an array of messages and returns the array of messages sorted. In the fetch messages method we will pass the data and have it sorted. We will now see the messages in sorted order on the homescreen.
Sending Messages Between Apps - 1:40:00
We open up Android Studio with the app and run it on an android phone. We find a bug with the different screen sizes when running on different phones and learn that during development trying on different devices is important. We also had an extra closing tab that was crashing the app in the home screen but it only crashes on Android. We also have to allow http requests on Android. This is why it is good to check as you go along as you may have 15 of these issues pile up at once. We will fix these in the next video.
Android Changes - 0:00
We are going to start by moving the tab bar to the bottom just like it is in our IOS. React navigation handles a lot of this stuff with an if Android do this if IOS do this you are able to browse the code if you want we are changing it due to preference. We are able to override what react navigation does. We get rid of some errors like onRequest close error. There is also an error in MessageShort with a floating message that crashes on Android but not IOS so we go ahead and delete that.
Matching Username to User - 14:30
We are going to send a username to the server and match it to the user id. Right now our user doesn’t have a username so we add one in Turbo. In the message route when we get toUser we will fetch that user and take its id. Then when we create the message we will substitute the toUser with the user id. We can then send messages across. We also need to handle the error if there is not a user with the username specified. We have to handle the message on the client side by checking for fail in the data confirmation.
Infinite Scroll - 48:30
To begin we create more messages so we can test with them. We now go to our fetch command and create a page where we ask for a certain page of results. So we need to go to our backend and add support for fetching pages. We are going to create pages of 10 by slicing them from page length multiplied by the page minus page length to page length multiplied by page. When we get to the end of a page we want to fetch more messages. We have to add these new messages onto the old messages. We add an activity indicator to the fetching messages. We also make sure that if we are fetching a page we do not continue to fetch pages. We also make it so if we get to the end of the list and we get a success with nothing we stop the requests.