Add React Native Navigation on macOS with React Navigation

Project Source Code

Get the project source code below, and follow along with the lesson material.

Download Project Source Code

To set up the project on your local machine, please follow the directions provided in the README.md file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.

This lesson preview is part of the Building React Native Apps for Mac course and can be unlocked immediately with a \newline Pro subscription or a single-time purchase. Already have access to this course? Log in here.

This video is available to students only
Unlock This Course

Get unlimited access to Building React Native Apps for Mac, plus 70+ \newline books, guides and courses with the \newline Pro subscription.

Thumbnail for the \newline course Building React Native Apps for Mac
  • [00:00 - 00:12] So far our application is pre-functional, but it only contains one screen, which is not very useful. So we're going to set up multiple screens using React Navigation.

    [00:13 - 00:28] There are many React Native libraries for navigation, but not all of them support macOS, and React Navigation just recently added support for it. So not everything is working, but it's definitely functional.

    [00:29 - 00:50] So in order to install React Navigation, we're going to add the following dependencies. React Navigation Native, React Navigation Stack, Save Area Context, and React Native Screens.

    [00:51 - 01:09] So unlike all the other dependencies we have installed so far, these dependencies actually contain some native code, which means we cannot just add them into our JavaScript code. We actually need to recompile our app first in order for them to be available on the native side.

    [01:10 - 01:22] So in order to do this, I'm just going to close my main application. And just to be careful, I'm also going to close the metro package.

    [01:23 - 01:55] And I'm going to go into the macOS folder, and inside of the macOS folder, I'm going to do a port install command. So what this does is now that you have added the dependencies on the JavaScript site, and since they have some native components, you actually have to tell the Xcode project or via co-op, that these dependencies need to be installed or need to be imported into the entire Xcode pipeline.

    [01:56 - 02:04] So now that they are installed, I can just go back and run my usual macOS command. And this will compile my app one more time.

    [02:05 - 02:21] Great. Let me just reload one more time.

    [02:22 - 02:31] Oh, yeah, I actually need to restart the backend server. No.

    [02:32 - 02:39] All right, perfect. So I'm just going to close this here one more time.

    [02:40 - 02:48] All right, cool. So we now need to set up a router.

    [02:49 - 02:58] A router is the component that's going to handle or it's going to contain all the routes. And that's where we will navigate to a different part of our application.

    [02:59 - 03:04] Now we mentioned before, there is a difference between containers and components. And now is the time to talk about this.

    [03:05 - 03:18] So the basic idea is that containers are going to be the components on the top most level, right? Those are the ones that are direct children's of a router.

    [03:19 - 03:35] And components can be or should be a lot smaller. That way it gets a little bit easier to know when a component is the utmost parent of your component tree.

    [03:36 - 03:50] And that's quite useful because sometimes the almost parent is the one that might have direct access to props or might get injected some other properties via the router or what not. Right?

    [03:51 - 04:07] So this is a very useful pattern to follow because it's going to save you a little bit of time whenever you need to access, especially when you need to access the navigation state. So we're going to start by creating a route folder.

    [04:08 - 04:23] So for my start folder, I'm going to create a routes.tsx file. But again, I'm just going to take the same code that's on the lesson.

    [04:24 - 04:31] And let's just walk over it. Let me just fix.

    [04:32 - 04:41] I changed the name of this one. Dynamic color.

    [04:42 - 05:02] And yeah. So I need to fix this one as well.

    [05:03 - 05:11] All right. So this is our routes component.

    [05:12 - 05:31] And first, the first thing that you're going to notice, let's ignore the imports for a little bit, there's a type that I have created here. So this type is supposed to mimic all the routes that you create inside of your router.

    [05:32 - 05:37] And the type of these routes is going to be the parameters that the route itself takes. All right.

    [05:38 - 06:02] So this book container, this book route takes a title string that is every time you navigate into this route from any other route, you should also send a title along with it for the component to do its job to display itself properly. Same goes with the home route.

    [06:03 - 06:11] This one takes nothing because it's the home route is the application start. But this kind of gives you a lot of type safety, right?

    [06:12 - 06:20] Especially because containers, they leave completely separated from each other. So sometimes when you're navigating routes, you might forget to send something.

    [06:21 - 06:30] So the latest version of React Navigation has implemented this type safety. And it's quite useful actually.

    [06:31 - 06:42] So now that we have our parameter list, we can actually create a stack navig ator. So a stack navigator, the name implies it is just a stack, right?

    [06:43 - 06:54] As you go navigating between screens, that will go piling up on it on top of each other. And you can navigate back and you're just going to go down the stack.

    [06:55 - 07:01] So it's just what its name says. Now this is not the only navigator that React Navigation offers.

    [07:02 - 07:06] There's a few of them. There's the menu navigator, the sidebar navigator.

    [07:07 - 07:10] There's the bottom bar navigator. And maybe there's one or two more.

    [07:11 - 07:20] But these are all the patterns that you see in most apps nowadays, right? You see a bottom bar, you see a stack navigator, you see a many bar or a sidebar.

    [07:21 - 07:26] So you can mix all of them. You can put a stack navigator inside a bottom navigator.

    [07:27 - 07:32] You can put a bottom navigator inside of stack navigator. It's quite flexible in that regard.

    [07:33 - 07:41] And afterwards, we just pass our stack parameters. So the navigator can type check all of our routes.

    [07:42 - 07:46] Great. So what else do we have here?

    [07:47 - 07:53] One second. Yeah, this.

    [07:54 - 07:58] So this just books. Great.

    [07:59 - 08:05] So our right component is just a functional component. Inside of it, I'm using a dynamic color.

    [08:06 - 08:22] We'll see in a little bit that it's used to tint our header. So we first need to take a root stack and put the navigator component that wraps all of our routes.

    [08:23 - 08:29] Then we can pass screen options. Now the screen options, it's quite long.

    [08:30 - 08:41] It has a lot of properties. I'm not going to show them to you, but basically you can customize a lot of the stuff within the navigator itself.

    [08:42 - 08:50] You can play with the style, play with the overlays, play with the shadows. You can set that style for the header.

    [08:51 - 08:57] You can directly set a title for the header. There's a lot of properties in here, as you can see.

    [08:58 - 09:05] So you can customize your application however you want. For now, I just pass in a style to the default header.

    [09:06 - 09:16] Sometimes you might even want to do your own header. But I'm just going to leave the header as it is from the default styles and I'm just going to pass a tint color to it.

    [09:17 - 09:26] Inside of the router, I created two routes, which are the screen object property. And I pass the name to it, which is important.

    [09:27 - 09:39] This is how we're going to navigate to this route. I'm going to pass the component, or in our case, the container that needs to be displayed within this route.

    [09:40 - 09:47] And one more time, I can just send an option, set the options in here. Or you can also do it inside of the component.

    [09:48 - 09:56] Once the component has mounted, you can actually set the navigation options. But for now, I'm just doing it on this level.

    [09:57 - 10:07] So I have two routes, my home route and my book route. I haven't created my book container yet, which is something that I'm going to do next.

    [10:08 - 10:24] So once again, I'm just going to take the code from the course. I'm going to create a new book container.tsx file.

    [10:25 - 10:33] I'm just going to paste it. So right now, I'm just going to leave it empty.

    [10:34 - 10:43] It's just a text for me to test that my router working. I'm going to export it.

    [10:44 - 10:56] So here, I can just go and just replace this. And I'm going to go here.

    [10:57 - 11:02] This is my book. And I'll just rename a few stuff.

    [11:03 - 11:07] Great. So you can see my application reloaded itself.

    [11:08 - 11:16] So I have my two routes registered on my router. However, I still cannot access it because I haven't mounted it.

    [11:17 - 11:48] So now I'm going to go into my app.tsx file and I'm going to import navigation container, which is the utmost, utmost component that you need to mount navigation. So I'm going to put it below my store because my store does not need the navigation to work.

    [11:49 - 11:57] The state is separate from the UI. And what does this say?

    [11:58 - 12:05] Navigation container. Great.

    [12:06 - 12:20] And inside of my navigation container, instead of directly putting my books container, I'm going to put my routes component. Great.

    [12:21 - 12:24] So now my application is still running. I can reload it.

    [12:25 - 12:36] Everything is still fine. So now my routes are somewhere in there, but I cannot navigate through them yet because I haven't put any way to navigate through the routes.

    [12:37 - 12:47] So in order to do this, I'm going to go to my books container. And inside of it, I'm going to use another hook.

    [12:48 - 13:01] This hook I'm going to call navigation. And it is the used navigation hook from React Navigation Core.

    [13:02 - 13:18] It might be native, but we'll give it a try. So what I'm going to do is I'm going to wrap my each of my books so that it navigates to a detail page from that book.

    [13:19 - 13:27] So I'm just going to use a touchable opacity. I'm going to put my view inside of it.

    [13:28 - 13:39] I'm just going to move this key, which is important for React Native to render this stuff. And on the onPress function, I'm going to create a new function for each book.

    [13:40 - 13:52] And inside of it, I'm going to say navigation.navigate. And I have to pass the route name.

    [13:53 - 14:04] So if I take a look into my route file, what I called it was book. So I'm going to navigate to the book container.

    [14:05 - 14:11] And let me just reload it to make everything working correctly. And here you see.

    [14:12 - 14:25] So undefined is not an object because we haven't passed the title, right? So like we said, our book route takes a title, which is something that I need to work properly.

    [14:26 - 14:42] So I'm going to book back to my books container. And here as the second parameter, which is the state that we're going to send, as a title property, I'm going to send the book title.

    [14:43 - 14:48] Now if we navigate, there you go. That's how navigation works.

    [14:49 - 14:55] [music playing]