1. 12
    Render Nested Routes in Remix
    4m 9s

Render Nested Routes in Remix

Kent C. Dodds
InstructorKent C. Dodds

Share this video with your friends

Send Tweet
Published 3 months ago
Updated 3 months ago

We need to create an admin route where we can create and edit our blog posts.

First we’ll make a /admin route that has some JSX and a loader that returns all of the posts. But how do we create different pages for admin actions without repeating all this code? This answer is to use Remix’s nested routing feature!

Start by following a convention of naming a folder identically to your route, and having sub files that correspond to different sub pages such as index, new, and so on. Then in your AdminRoute, render the <Outlet /> component. This tells Remix to render nested routes in its place!

The index.tsx nested route will be the one that is rendered by default. In the index you can link to the other nested routes using Remix’s Link component.

Kent C. Dodds: [0:00] I want to have a link here called admin that will allow me to create and edit posts. We're going to go to our index here. Right above our list, we'll add this link to admin. This is a relative route, so this is going to point to a file that's within the post directory.

[0:17] Let's make that admin.tsx. Here, let's export default a function that is our AdminRoute(). Here, we'll return a bunch of JSX that I'll just paste in here. We're going to need some posts, so let's go ahead and say posts here. We'll destructure that from useLoaderData() coming from @remix-run/react. Let's also get link from @remix-run/react. We'll fill this little bit in a little bit later.

[0:48] Now, where are we going to get these posts? We're going to get it from the loader. Let's export const loader, which is a LoaderFunction, and that's going to come from @remix-run/node. This is an async() function. Here, we want to return JSON from @remix-run/node, which is going to return a posts object.

[1:09] Here we need the posts listings again, so we'll wait, getPostListings. With that, we should be set to go to this page.

[1:18] If we go admin, there we go. We've got our list of posts right here, and then we've got a space right here. When I select these different posts, I should see this part of the page update.

[1:28] Here, we're going to be doing some nested routing. To make this work, we're going to create an admin directory. Inside of there, we'll have an index.tsx. That is what's going to be active when we're on this page posts/admin. When we're on these additional pages of post/admin and then my-first-post, we should show that post, and it'll show up right here. We'll get to that a little bit later.

[1:54] We want to have our index filled in, though, so let's export a default function called AdminIndexRoute(). Here, we'll say link, Create new post, and we'll link that to new. This link is going to come from @remix-run/react. Then we'll create a new.tsx so that link can point to something. We'll export default NewPostRoute and return. We'll put an h2 for new post. We'll get to the form a little bit later.

[2:28] With that, we come over here, and we're still getting the . . ., and that's because the parent route of admin isn't telling the router where to put its children. Let's go to the admin parent route. Instead of the . . ., we're going to say Outlet, and that's going to come from @remix-run/react as well.

[2:47] With that, we come over here, and boom, we've got to create new post link. That's not styled, so let's go ahead and style that really quick here. Now, this is styled, and it looks nice. We click on that. This part of the UI updates to our NewPostRoute. We can navigate back to get to the index route.

[3:05] In review, what we've done here is we created an admin route right here, and it's doing our typical loader stuff, listing out the different posts that we have. Then it has a main where we're rendering an Outlet, which communicates to the router, if this route has any children, that's where those children should be placed.

[3:23] We linked to this from our index. Then we create the children routes for the index, which is to say that, if there is no child route active for the admin route, this is what should be placed in the Outlet position. Then, when we're on the new child route for admin, this is what should be placed inside of the Outlet.

[3:42] That association is created via the convention of the name of the route, and then a folder with routes underneath it. While we're here, let's go ahead and make TypeScript happy about this.

[3:54] Let's make a LoaderData. We're going to borrow this from the post because it's the exact same data. We'll say json is our LoaderData and make this as LoaderData. Now we're type-checking and auto-completing and all that stuff here, so we're good.