T
TanStack17mo ago
constant-blue

How do I render a Default (root level) Not Found Component within a layout.

Hi, I would like to render all notFound components within a layout. Is there a simple way to achieve this? I am using file routing, vite, react and typescript. I have tried adding a notFound component to a pathless _layout.
export const Route = createFileRoute('/_layout')({
component: LayoutComponent,
notFoundComponent: () => <div> Not found at root but inside a layout </div>
})
export const Route = createFileRoute('/_layout')({
component: LayoutComponent,
notFoundComponent: () => <div> Not found at root but inside a layout </div>
})
When navigating to '<host>/wrongpath', only the default NotFoundComponent is rendered without the layout. Other options I have considered: 1. Moving my layout to __root.tsx. The problem with this is that I have some routes I would like to render without the layout. Adding the _ suffix to them doesn't seem to bypass the root route as a parent. 2. Including the layout in the path and passing from props to make Link's relative. This ensures that invalid links that I generate are caught and improves some UX, but doesn't catch <host>/wrongpath URL's. 3. Wrapping my NotFoundComponent in the Layout component. Is this even allowed? Does <Outlet> work like a child if used outside of the router? 4. Catching a NotFoundError and re-directing to a NotFound route within the _layout. I don't really want to introduce too much boilerplate with this and it would mean changing the URL that the user see's. Am I missing something for this task that I would have thought is fairly trivial? Any help would be appreciated. Thanks in advance and thanks to the developers of this library. Regards, Simon
11 Replies
foreign-sapphire
foreign-sapphire17mo ago
I think notFound needs to be below the layout in order for the layout to render if there's a match
constant-blue
constant-blueOP17mo ago
Okay, I don't suppose there is any way to have a match that's underneath the layout but matches anything not already handled? I have a home page underneath _layout that renders with '<host>/' inside the layout, however adding my NotFoundComponent to the '/_layout/' HomeComponent route doesn't seem to help either.
foreign-sapphire
foreign-sapphire17mo ago
I'd need to see a reproduction. can you try to fork one of our stackblitz examples ?
constant-blue
constant-blueOP17mo ago
SFransenK
StackBlitz
Router Basic File Based Example (forked) - Not Found in Layout - St...
Run official live example code for Router Basic File Based, created by Tanstack on StackBlitz This fork attempts to add a not found page embedded in a layout that is displayed for root not found routes.
constant-blue
constant-blueOP17mo ago
I added notFoundComponents to _layout.tsx and _layout-2.tsx. When navigating to <host>/layout-c, I would like to see "I'm a layout" and then "404 Not Found configured in _layout"
foreign-sapphire
foreign-sapphire17mo ago
so your navigation is to="/this-route-does-not-exist". If you look at the router devtools, you'll see that the only match is the __root__ route. That's why you see the not found from there. why would it show the one from a layout that it's not matching ? if you go towards to="/layout-a/this-route-does-not-exist", then you'll see the 404 configured in layout-2
constant-blue
constant-blueOP17mo ago
I understand that this isn't a right answer. I am asking how to embed a root 404 within a layout. If possible...
foreign-sapphire
foreign-sapphire17mo ago
I don't think I understand the use-case. links have a structure, and the router renders what matches that structure. If you go to a page that doesn't match anything but the root route, how should we render something from a layout that is not matched at all?
constant-blue
constant-blueOP17mo ago
I have a header with logo and some nav items on my layout that I would like to render around my not-found page. I would like the not-found page to render for all not-found routes. I also have some pages that don't utilize the header, so don't want to put it into the root layout. I have updated the forked example to demonstrate the use case better. Clicking the Signup link correctly takes us to a route without a header. Clicking the 'This Route Does Not Exist' causes the header to disappear. The header disappearing seems like a jarring user experience and I thought there might be a simple answer that I was missing. I thought maybe there would be something similar to how errors can be targeted to route-id's.
foreign-sapphire
foreign-sapphire17mo ago
I would say there are two ways: - put the header in the root layout (but you already said you don't want that) - render the header manually in the notFound component (I think that's not bad)
constant-blue
constant-blueOP17mo ago
Okay, thank you. Do you know if react or the router is smarter enough to not re-render the header if I wrap the not found component with it separately from the layout? Would I get a screen flicker and pending component? If I put the header in the root layout, is there a way to render another route as a sibling to the root layout? ie without rendering the root layout. I guess I could conditionally render the header with react props.

Did you find this page helpful?