- Read Tutorial
- Watch Guide Video
I'm gonna open up our Container component here, and I'm first gonna get rid of the text content, and then I'm gonna remove that from here.
Container.tsx
import React from "react"; import { View } from "react-native"; interface IContainerProps { children: any; } export default (props: IContainerProps) => { return ( <View> {props.children} </View> ); };
And just for the sake of you being able to see everything that's going on here at the same time, I'm actually gonna start off by creating our bottom tab bar, inside of the Container file.
Eventually, I'm gonna move it to its own dedicated file, but I think it helps to be able to create this here in the same file so that you can see all of this and you can see it happening, you can call the component, you can have all of your code right in front of you at the same time. Whenever I'm working on something new, or maybe something that is a little bit more challenging, I like to do that, and react gives you the ability to have that kind of flexibility.
So let's get started here, I'm gonna create a interface for the bottom tab bar, so its gonna, let me call it, IBottomTabBarProps
, and then inside of here, we're gonna have really just one thing that we need passed in, and that's gonna be our navigation element, so this is gonna be our navigate function. This is the same thing if you go back to our Feed Screen, it has access to the Props for navigation and navigate, and then it can be passed down.
Now one thing that's gonna be a little bit tricky here, is that Container is not automatically going to have access to this navigate function. So we're gonna have to get a little bit tricky here, and what we're gonna have to do is actually pass in, navigate as a Prop to Container, so that the bottom tab bar has access to it. And that may seem a little bit tricky or convoluted, do not worry, we're gonna walk through it, and I think it will make sense after you see everything that's happening.
So here, I'm going to take a look at what we had on our FeedScreen, for navigate because this is gonna be exactly the function that we're gonna wonna have access to inside of our bottom tab bar. And the reason for that is because if you imagine, if you've used applications like Instagram or Facebook, each one of those little icons that you see, down on the bottom of the screen, those are really just links, if you think about it, so we're gonna also pull in our own icons, and you're gonna be able to see, how you can make icons clickable.
But as far as we're really concerned from pure functionality perspective, those are simply links. So we're gonna need access, we're gonna have to have access to navigate, we're eventually gonna have to put this navigate function inside of our Container Props as well, so that's gonna be something that we'll do later on, but I'm not gonna worry about that at the moment. So let's go back, I'm gonna close out SearchScreen, I'm gonna close out all of these files just to make it a little bit easier for us to see. So these are only the files that, we have to have access to here.
So let's come and let's start building out, the actual bottom tab bar. I'm just gonna make this const and the reason for that is because when you say export default in a file, just as a JavaScript reminder, this doesn't have anything to do with React or React Native. Anytime you say export default in a JavaScript file, you can't say export default for anything else. And the reason for that is because whenever you do something like import the Container here, the default is, okay, you can only have one default, because that's what is automatically gonna be pulled in.
So when we called Container here, what JavaScript did is, it looked in this Container file. And because we didn't wrap it up in curly brackets, like for example, how React Native did it, because of that, it's looking for an export default, and then it applies that and saves it inside of this Container import statement, so that's a reason why we can't do an export default.
So here, I'm just gonna make it a standard function component. So let's just call it Bottom Tab Bar and this is going to accept the props, from IBottomTabBarProps, and then also make this a fat arrow function, so type return here, and this is gonna start by just being a view. So this is gonna start by just being a view tag, and inside of here, let's once again, let's just test this out.
So I'm going to bring in a couple more components, from React Native, so I'm going to say Touchable Opacity, and text, just so we can test this. And so inside of here, we're gonna have a few other components. So we're gonna say I wanna have that Touchable Opacity component and inside of it, I wonna have a text component, so here we can say Feed for one, and then let's do another one for Search, and then let's do one for, we can just call it like Form what we're gonna change this eventually, because we're gonna be using icons, and then account or you could call it settings or something like that.
Container.tsx
const BottomTabBar = (props: IBottomTabBarProps) => { return <View> <TouchableOpacity><Text>Feed</Text></TouchableOpacity> <TouchableOpacity><Text>Search</Text></TouchableOpacity> <TouchableOpacity><Text>Form</Text></TouchableOpacity> <TouchableOpacity><Text>Account</Text></TouchableOpacity> </View> }
So this is a good first step for, what we are gonna need for our bottom tab bar. So let's hit save here, and then let's call bottom tab bar, so I'm gonna come down here, and below props children or after it technically, then I'm going to call BottomTabBar, and make sure we pass in props. Right now, we don't have access to this, so we're gonna have to just write the code as if we did have it and then we'll go at those in later.
So I'm gonna say navigate is going to be our prop, and we're gonna imagine that we're getting props.navigate. Now notice we're gonna get an error here, because TypeScript is looking at our interface and it's saying, you don't have anything called navigate, but we're gonna fix that here shortly. So let's go now to the Feed Screen and go to the Container Component, and now let's pass in props navigate.
So I'm gonna say navigate, and pass in props.navigation.navigate.
FeedScreen.tsx
export default (props: IFeedScreenProps) => { return { <Container navigate={props.navigation.navigate}> <Text>Feed screen</Text>
And then we also need to go and extend that interface inside of the Container. So let's come up here and we can just copy this because it's gonna be the exact same thing. Okay, we can hit save here, and we can hit it save here.
Container.tsx
interface IContainerProps { children: any; navigate: (arg: string) => void; }
Okay, so what is going on here? Let's take a look at it, and we can get into where we're gonna definitely walk through every line of code there, because I know that, that was a quite a bit of functionality added in a short period of time. So first, let's start in our Container File, so we created a bottom tab bar component here, it's taking in Props, we're not using them yet, but we will shortly. And then inside of here, it has a bunch of links, It has a Feed link, Search, Form and Account. And you can see this is all working, each one of this is a link that got added, and I know it looks like there's some duplicate content here because we have Search and Search, but that's just because we have that in our feed screen, we can actually get rid of this just so that it doesn't look like we have that duplicate content.
FeedScreen.tsx
export default (props: IFeedScreenProps) => { return ( <Container navigate={props.navigation.navigate}> <Text>Feed screen</Text> </Container> ); };
Okay, so now we have the start of our bottom tab bar, right here we have a Feed link, Search, Form and Account, just like we have right here.
Now inside of our Container we've extended that, we've now required two Props, we now say that a Container needs to have children which we already knew about. That's all of the content that gets passed in whenever the Containers called. But then we're also saying that a Container always needs to have this navigation function or this navigate function, passed to it, takes in a string, and returns void.
So that is pretty cool, we've been able to in a pretty short period of time, build out an entire workflow, where we have a component that is able to navigate users from one part of the application to another one. And this is something that can be called from all of those other accounts, or from all of those other screens, like Account, like Search as long as we call Container, it's gonna have access to that, which I think that is pretty cool, when it comes to building your React Native applications. It's a really neat way of being able to share functionality.
So with all of this in place, now let's test it out, and let's make sure, that these Touchable Opacity functions or components, can actually navigate the user. So let's come first to let me open up the router, and I wanna make sure I have my names correct, so we have Feed, Search, Account and Post Form. So let's test this out on the account one, because we haven't tested that one out yet.
So I'm gonna go to Touchable Opacity, and I'm gonna add a on Press handler, kinda like we've done before, and inside of here, I'm gonna pass in an anonymous function, so it's going to be a fat arrow function, and I'm just gonna say props.navigate, props navigate, and let's pass this to account, hit save, and let's see if this works.
Container.tsx
<TouchableOpacity onPress={() => props.navigate("Account")}> <Text>Account</Text> </TouchableOpacity>
So if I come here and press account that worked perfectly, so now we have a way of navigating to each one of this and just because we can let's go and populate this for each one of these other components. So this next one was called Post Form, so to do that, we can just change Account to Post Form, and then we can do the same thing, we can copy that on Press handler and at this for Search, and then for Feed.
Container.tsx
const BottomTabBar = (props: IBottomTabBarProps) => { return ( <View> <TouchableOpacity onPress={() => props.navigate("Feed")}> <Text>Feed</Text> </TouchableOpacity> <TouchableOpacity onPress={() => props.navigate("Search")}> <Text>Search</Text> </TouchableOpacity> <TouchableOpacity onPress={() => props.navigate("PostForm")}> <Text>Form</Text> </TouchableOpacity> <TouchableOpacity onPress={() => props.navigate("Account")}> <Text>Account</Text> </TouchableOpacity> </View> ); };
Okay, let's hit save, and now let's test this out, if I click on Form, Post Form screen, I click on Search takes me there, let's click on Account and then let's go back to Feed and you can see it doesn't take us anywhere because we're already there.
So this is all working really nicely if I click on Search, and then click on Form, then you can see it's giving us an error,
and we can see what that error is gonna be, if you would like to, we're eventually gonna populate all of this, but open up the Search screen and see why that is coming up with the error. and you can see we already have a warning,
and it's because we're not passing in, that navigate function.
So let's do that, let's first build out an interface, and really, we can just copy this interface from the IFeed Screen Props. So let's paste that in, and let's change the name to Search screen, and then for the Props, just pass in Props, I Search Screen Props, and now for Container, we can pass in the navigate prop because that is a required one as you can see, or else you're gonna run into an error like that. And then we'll just pass in props.navigation.navigate and hopefully you can see really the huge benefits that you get from working with TypeScript, because right there without us having to reference any documentation or anything like that, we instantly were able to see and get IntelliSense to get recommendations for how we should write our code and what functions we have available to us. So using TypeScript and using interfaces is really is a great way of being able to streamline your workflow.
SearchScreen.tsx
import React from "react"; import { Text, View } from "react-native"; import Container from "../components/layouts/Container"; interface ISearchScreenProps { navigation: { navigate: (arg: string) => void; }; } export default (props: ISearchScreenProps) => { return ( <Container navigate={props.navigation.navigate}> <Text>SearchScreen</Text> </Container> ); };
So let's test this out, now that we have that working. So I'm going to hit reload, and let's go to the Search screen now, and let's go to the forum page, and you can see that worked perfectly.
And you can also see, the way the React navigation stack system works. So I talked about a Stack, as being things like where you have these screens that are essentially piling on top of each other.
So I'm gonna give you a little bit of a visual representation of it here in comments, so when the screen and the entire app loads up, it loads up with the Feed screen on the Stack. Right now that's the only one on the Stack. When we click the link, the way that the navigation system works, is it added something else to the Stack, it added, in this case, the Search Screen, so now we have the Stack and it has two items, now we clicked another link, now we have added the Post Form Screen to the Stack, and so now we have these three.
// PostForm // Search // Feed
The reason why this is necessary is because it's kind of like the way, the Back button works in a browser, if I wanna be able to click back, so I click Search and then Feed, the way react navigation works. It needed to keep track of each one of this, because when I went up here and I click back, the way that it worked is react navigation removed Post Form from the Stack. So now the Stack only had two items, and then if we remove Search and hit back again, then it removes Search from the Stack, and then we're back with one final item.
So hopefully, if the whole Stack navigator, and some of the routing words like where we have the stack navigators, if that was confusing, hopefully seeing how it works, especially with nested routes, hopefully, that starts to make a little bit more sense on how you can build out your navigation system. And the bigger we make this application, the more we're going to start working with the router, so hopefully, you're gonna understand it even a little bit more.
So great job going through that, we now have our own bottom tab bar. But as you may notice, it's not on the bottom, it doesn't have icons, it doesn't have styles, it doesn't have anything like that. So because we have our working functionality though, we are ready to move on to the next guide, where we are going to be able to start adding our own custom styles to this application.