diff --git a/packages/react-router/src/renderRouteNotFound.tsx b/packages/react-router/src/renderRouteNotFound.tsx index 225a013beae..ab2fd4c4945 100644 --- a/packages/react-router/src/renderRouteNotFound.tsx +++ b/packages/react-router/src/renderRouteNotFound.tsx @@ -16,20 +16,25 @@ export function renderRouteNotFound( route: AnyRoute, data: any, ) { - if (!route.options.notFoundComponent) { - if (router.options.defaultNotFoundComponent) { - return - } + let routeWithNotFound: AnyRoute | undefined = route + while (routeWithNotFound && !routeWithNotFound.options.notFoundComponent) { + routeWithNotFound = routeWithNotFound.parentRoute + } + + if (routeWithNotFound?.options.notFoundComponent) { + return + } - if (process.env.NODE_ENV === 'development') { - warning( - route.options.notFoundComponent, - `A notFoundError was encountered on the route with ID "${route.id}", but a notFoundComponent option was not configured, nor was a router level defaultNotFoundComponent configured. Consider configuring at least one of these to avoid TanStack Router's overly generic defaultNotFoundComponent (

Not Found

)`, - ) - } + if (router.options.defaultNotFoundComponent) { + return + } - return + if (process.env.NODE_ENV === 'development') { + warning( + false, + `A notFoundError was encountered on the route with ID "${route.id}", but a notFoundComponent option was not configured, nor was a router level defaultNotFoundComponent configured. Consider configuring at least one of these to avoid TanStack Router's overly generic defaultNotFoundComponent (

Not Found

)`, + ) } - return + return } diff --git a/packages/react-router/tests/not-found.test.tsx b/packages/react-router/tests/not-found.test.tsx index ce8bdf1207f..a0267ede0a7 100644 --- a/packages/react-router/tests/not-found.test.tsx +++ b/packages/react-router/tests/not-found.test.tsx @@ -245,3 +245,75 @@ test('defaultNotFoundComponent and notFoundComponent receives data props via spr const errorMessageComponent = await screen.findByTestId('message') expect(errorMessageComponent).toHaveTextContent(customData.message) }) + +test('pathless layout route notFoundComponent is used when child has none (issue #6351)', async () => { + const rootRoute = createRootRoute({ + component: () => ( +
+ +
+ ), + }) + + const authenticatedRoute = createRoute({ + getParentRoute: () => rootRoute, + id: '_authenticated', + component: () => ( +
+ +
+ ), + notFoundComponent: () => ( +
+ Authenticated Not Found +
+ ), + }) + + const agentsRoute = createRoute({ + getParentRoute: () => authenticatedRoute, + path: 'agents', + component: () => ( +
+ +
+ ), + }) + + const agentsIndexRoute = createRoute({ + getParentRoute: () => agentsRoute, + path: '/', + component: () =>
Agents Index
, + }) + + const skillAgentRoute = createRoute({ + getParentRoute: () => agentsRoute, + path: 'skill-agent', + component: () =>
Skill Agent
, + }) + + const router = createRouter({ + routeTree: rootRoute.addChildren([ + authenticatedRoute.addChildren([ + agentsRoute.addChildren([agentsIndexRoute, skillAgentRoute]), + ]), + ]), + history, + defaultNotFoundComponent: () => ( +
Default Not Found
+ ), + }) + + window.history.replaceState(null, '', '/agents/non-existent') + + render() + await router.load() + + const notFound = await screen.findByTestId( + 'authenticated-not-found', + {}, + { timeout: 1000 }, + ) + expect(notFound).toBeInTheDocument() + expect(screen.queryByTestId('default-not-found')).not.toBeInTheDocument() +})