- Read Tutorial
- Watch Guide Video
As you may have seen, it's quite a bit different than a standard web application and how the routing works there and so as you go through this and as you build more and more apps, it's gonna become second nature to you.
So in this guide, I'm going to start by building out the type of app container that we're gonna wanna work with in building out our routing engine. So I'm going to open up the file system here to the left and I'm gonna create a new directory here and I'm gonna call it utils
, short for utility. So I'm gonna say utils/ and then I'm just gonna call this the router file. Now, this is going to be a router file, I'm going to make it a tsx file. You're gonna see, as we go through this course, most of the components in the files we build are gonna be tsx and then a few of 'em will be ts.
The difference between the two is tsx means that we can put JSX. So we can put calls to components and things like that in the file. If it's just ts, it's just gonna be a pure TypeScript file and we're gonna do that later on so you'll be able to see the difference between both. But for this one, I'm just gonna call it router.tsx because as you're gonna see later on, we are gonna bring in some components.
Now let's start to build out this file. The very first thing that I'm gonna do is I'm gonna import React from react and then from there, I wanna bring in a couple of the functions that we already imported. Now, these are gonna hopefully look a little bit familiar because you went through the documentation and so we're gonna start by pulling in a app container and a switch navigator from React navigation.
So I'm gonna say import, and now these are not default imports or exports, so the way that we can call React by itself without the curly braces means that that is the default export from the React library. But these are not gonna be the default exports, so we're gonna have to put them in curly brackets. So I'm gonna say createAppContainer
and then createSwitchNavigator
and if you're wondering how I was able to pick out those names, it was from reading the documentation. That's the reason why I wanted you to do that in the last guide and those are from react-navigation. And then let's also pull in now the createStackNavigator
. So I'll say import createStackNavigator and that's going to be from the react-navigation-stack library.
router.tsx
import React from "react"; import { createAppContainer, createSwitchNavigator} from "react-navigation"; import { createStackNavigator} from "react-navigation-stack";
Now, from here, I need to import the screens. So right now, as you can see, if I go to screens, and you know what? It looks like I made one mistake. Do you notice how I put the utilities in the screens library?
Before we go too far, let's actually fix that. I want the utils at the root of the project. So there's a couple of ways of doing that. The easiest way is just to click on that and then drag it into the root and now you can see, it's on the same exact level as screens.
So if you ever happen to do that, that's how you can move an entire directory and so let's open up that file once again and everything is the same. So that's something important to keep in mind.
Now, for our screens, you can see we have a FeedScreen but in order to make sure that this is actually working, I think it makes sense to create another screen. So we can just click right on FeedScreen and let's copy it and then paste it inside of the screens directory, and here I'm gonna change the name and this is gonna be our SearchScreen because we are eventually going to do that. So I'm gonna say SearchScreen. I'll copy that and just here in the Text component, just paste that in just so we can tell the difference. Hit Save and then you can close both of those files because we're not actually gonna do anything with them, we're just using them for our routing.
So now with that in place, we can actually import those files and those components. So I'm gonna say I wanna import the FeedScreen from and now the path to this, I'm gonna do two dots, so I'm gonna jump back one directory 'cause remember, we're in the utils directory and then I'm going to go and grab the screens directory and then the FeedScreen and then I can just copy this line and then for the SearchScreen, we're gonna call it SearchScreen and we know that that is inside of our screens directory. So now we've imported all of the dependencies that our routing engine and our navigation engine is going to work with.
router.tsx
import React from "react"; import { createAppContainer, createSwitchNavigator} from "react-navigation"; import { createStackNavigator} from "react-navigation-stack"; import FeedScreen from "../screens/FeedScreen"; import SearchScreen from "../screens/SearchScreen";
So now what we can do is actually create a couple things. We're gonna create a StackNavigator and then we're gonna create an app container. So let's start by creating what's called an AppStack. So I'm gonna create a variable called const AppStack and then this is going to utilize the createStackNavigator.
router.tsx
const AppStack = createStackNavigator
Now, I don't want you, if you've never worked with the StackNavigator and it's still a little bit fuzzy, even after going through the documentation, don't get too hung up on the syntax here or what it's doing, just follow along and one of the things I've noticed with this is that working with routing and learning how routing works inside of mobile applications, it really starts to make more sense as you see what's happening.
So if this is looking really confusing, don't get frustrated right now. We can just start taking it one step at time and you'll see exactly how it works and then you'll be able to adjust it from there. Now, createStackNavigator, we can tell because it starts off with a lowercase and it follows this camel case type of convention, that's usually a pretty good indicator that this is a function.
So we are going to call this function by calling parens and then inside of here, we're going to be able to pass in some objects. Now, this documentation here looks kind of confusing. So let's not even worry about that too much right now, and let's instead, follow the documentation and let's pass in a few objects.
Now, the first object is gonna be the list of screens. So this is gonna be a set of key-value pairs so I'm gonna say Feed and then that's gonna be connected and mapped to the FeedScreen. And then I'm gonna say Search and that's gonna be mapped to the SearchScreen. And then we also want, so that's the first object so that's simply a nested object. It's an argument inside of createStackNavigator, and then the second object is gonna be a set of parameters.
Now, these are kinda like some configuration parameters that we wanna pass in to the StackNavigator. So the only one that I'm gonna do for right now is the initialRouteName. Now, because we're using TypeScript, we have some really helpful type of autocomplete here. So I'm gonna say initialRouteName and then this has to be a string.
Now, this is where it can get a little bit confusing because you may wanna pass in the string, 'cause I want my FeedScreen to be the initial screen that loads but we don't actually call FeedScreen, what we call is Feed. So the way that createStackNavigator works is it's a function, the very first argument is gonna be a mapping, a key-value mapping from whatever we want the screen to be called and then what we've imported.
So in this case, I'm bringing this in and I'm saying you know what? I want the FeedScreen to be called Feed and then anywhere else in the system, the way that you call it is by calling the name that we've provided here on the left-hand side. So hopefully that makes a little bit of sense. And so now with that in place, that's everything we need for AppStack.
Now what we can do is actually export our router and so we're gonna do that by saying export default and now we're gonna create a AppContainer, this is exactly what we brought in right up here. So we have created a StackNavigator and then a createAppContainer. So in our AppContainer, what we're gonna do is we're going to pass in, that's a function once again, and we're gonna start by creating a SwitchNavigator. So here is another function and the SwitchNavigator is kind of similar to the StackNavigator in that it takes in a key-value object first and then it has some other parameters right after that.
So the very first thing that we're gonna pass in it to create StackNavigator is our AppStack. So I'm gonna say that I want this to be called App and then that is gonna be mapped to the AppStack and that's our only item that we're passing in right now, so this is our only AppStack.
router.tsx
export default createAppContainer( createSwitchNavigator({ App: AppStack }) )
We're going to eventually be adding a few more, we're gonna be adding one for login and we're gonna be adding a few other ones like that and technically, you can have an unlimited number of the SwitchNavigators in place. So that's the first argument and then just like we did up here for our initialRouteName, how we passed in two objects, we're gonna do the same thing right here. So here, I'm gonna say the initialRouteName is going to be App, you can think of this kind of almost like these nested levels. So our AppStack is one level of our routing system and it contains all of these routes in it. Eventually, we're gonna pass in quite a few other routes and then we also can pass in some custom parameters.
Now, here, we're creating a SwitchNavigator which allows us to kind of abstract out how we are working with the application and with the routing engine and now we can say you know what, we wanna group this, we wanna have a set of these routes that are mapped just to App and anything inside of AppStack is going to be included in that. I know this could be a little bit confusing and the reason I know is because when I was teaching this to myself, I was very confused about the structure but I promise you, the more times that you go and you're building these applications, and you're working with it, it's gonna start to make more sense and once we see it working over here, it's really gonna make a lot more sense, so let's get started on that.
router.tsx
export default createAppContainer( createSwitchNavigator( { App: AppStack }, { initialRouteName: "App" } ) )
We've now created everything that we need to do in the routing engine, so let's go now back to the actual App component, and just so you can reference where that's at, it's at the root of the application. So here, what we can do is we can actually get rid of the FeedScreen and remove that call for the FeedScreen and now we can call our AppContainer so I'm going to come up here and let's import it.
So I'm gonna say import and we're going to our AppContainer and this is going to need one other function. We need to reference what we have here in the router and so when you saw, we have this createAppContainer, we're going to need that again so I can just copy this line. And just to make it easier to read, I'm gonna pull in just the AppContainer and then for AppContainer, what we're gonna do is we're gonna pull in our router that we already created.
So I'm gonna say import router, and you can spell this because remember, we exported this as the default. We could call this anything we wanted but I'm just gonna say import router from ./utils/router and now, I'm going to, and I made one mistake, AppContainer isn't an import, this is gonna be a constant, this is just a variable. So I'm gonna say our AppContainer is gonna be the createAppContainer and we're gonna pass in router as the argument.
App.tsx
import React from "react"; import { StytleSheet, View } from "react-native"; import router from "./utils/router"; import { createAppContainer } from "react-navigation"; const AppContainer = createAppContainer(router);
Now, I know this could look a little bit confusing, but don't worry, we're gonna walk through it. We are bringing in React navigation, we're pulling in the createAppContainer, and all this is in the documentation. So if you're wondering how I was able to do this or figure it our or anything, I literally just went through their tutorials, their documentation and that's how I pulled it out. And so this is this exact structure they recommend there.
From there, I'm creating this constant variables and I'm calling it AppContainer. You could call it anything you want but I think this is a good name for it and then I'm passing in the router. So everything that we included here, all of this code is now gonna be wrapped inside of this AppContainer variable and now, we can call this like a regular component. So inside of our AppContainer, we're going to just call our AppContainer and now we can hit Save and then we can watch it error out.
And that's perfectly fine. I'm gonna show you, this is a very common error. When I originally started working with this, I ran into these and so I'm gonna show you how to get past them. So right here, the error's pretty explicit. It says Error: undefined Unable to resolve module react-native-gesture-handler. What that means is that React Native is looking through the application and they can't find this.
Now, what you're gonna find out, assuming it works the same way for your system as it did for mine and I'm assuming as it about to, what this means is that it can't find these libraries and we're gonna have about two or three of these things that we're gonna have to install but the nice thing about these error messages is they tell us exactly what needs to be installed.
So we can open up the terminal here, and let's install this. I'm gonna say yarn
add and then react-native-gesture-handler
and if you look up here, that's exactly what it's asking for. It's saying that we can't find this react-native-gesture-handler library. So I'm just gonna do yarn add
and this is gonna go find the full list of dependencies that are needed for the gesture-handler and that's one of the items needed by the React system.
The reason why it's needed is because the navigation system that React Native provides has some really cool features such as being able to slide the screen from the left to the right, kinda like you'd see on applications like Instagram or Facebook or anything like that. So it's capturing those gestures and that's the reason why that is required.
I'm gonna fast forward the video just so we can get to the next dependency that it's gonna ask for. Okay, looks like it's done and I didn't even refresh anything here, the system automatically was able to do that so I'm gonna close the terminal. If you're curious on how I have it running, I actually have my terminal application that's running expo start so it's not running here.
So if I come now to the FeedScreen, and hit Refresh, then you can see we're still getting a error and that's perfectly fine. We're going to probably have a few more dependencies that we have to implement. So let's go and let's see what we need to do in order to pull those in. So right here it says Invariant Violation: Module AppRegistry is not a registered callable module.
So the very first thing that I'm going to do, whenever you see errors like this, lemme open up the terminal just so you can see this, and I'll also zoom in so it's a little bit easier for you to see.
I'm gonna stop the server itself and I'm gonna run expo start once again. Many times you'll see that many of the errors that you run into as you're building out these applications can be fixed by restarting the system. So I have the app running now and now let's open up the simulator once again. Okay, so simulator's ready. I'm gonna switch over to it, hit Refresh. Okay, perfect. So now we're onto the next error that we actually need to fix. So this is asking for another dependency.
So let's open this up and let's run yarn add react-native-safe and this one, let me just triple check that this is actually safe-area in there and not actually cutting off the word. Yeah, so it's safe-area-context.
Terminal
yarn add react-native-safe-area-context
So this is going to install this library. And this is the next one we need and we should only need one more after this. So we can hit Refresh. And perfect so now we're on the last one. This is asking for react-native-community/masked-view.
So yarn add
@react-native-community/masked-view
. Yarn will now install this package and after this, we should be good to good. So I'm going to fast forward it and then I will see you when it's done installing. Okay, it's completed and now let's come back to the application, hit Refresh, and there we go. So right now, it looks like we have an empty screen right here but that's perfectly fine. That's gonna be something we're gonna fix shortly but just know we are not seeing any errors. So it looks like all of our dependencies have been installed correctly so we are looking good.
Before I stop this video, I just wanna walk through this. I can say this might be one of the most confusing parts of the entire application process. So I don't want you to get intimidated or feel bad about not understanding all of this. This is very confusing if you've never built this out before. So let's just kind of review what we've done. We created a router component here. In this component, we've brought in three key dependencies. A AppContainer, a SwitchNavigator and then the StackNavigator. From there, we brought in the components that we wanna render out.
And then from that point, we created a AppStack right here that takes in a FeedScreen and the SearchScreen and then we added that to an AppContainer component. Inside of that, we're using a SwitchNavigator. If you're used to using tools such as React Router, this is very similar to the switch statement that React Router does. You're gonna see later as we add more routes that we're gonna put a few modules here.
So we're gonna have App, we're gonna have one called Auth and then we're gonna be able to switch between those navigation components and each one of those has its own set of routes. So the way I like to usually think about this is if you're creating journeys in your application. So say that you have a authentication journey where if a user's not logged in, the first thing they see is a login screen or a registration screen and you want them to be able go through a few different screens on there such as being able to reset their password or anything like that, those are all gonna be contained inside of their own stack and just like we're doing here, we're gonna have a FeedScreen, a SearchScreen, we're gonna have a FormScreen, we're gonna have a PostDetailScreen. Those are all gonna be nested inside of this navigator.
From there, we are creating an AppContainer for our entire application. And then we're putting the router, which contains all of the AppStacks, all of those things that we're gonna built out, they're all gonna be contained inside of here and lastly, we're simply calling that AppContainer. So all of that's getting rendered right here. So in the next guide, we're gonna start being able to render this out and we're gonna see how you can switch between screens.
So great job in going through that. I know that was a lot of material and it's always frustrating to see errors and those kinds of things but that's all part of being able to build these type of applications out. So very nice job going through that.