diff --git a/packages/react-router/src/Matches.tsx b/packages/react-router/src/Matches.tsx index c75fb19b8e0..1b7ec2cc6bc 100644 --- a/packages/react-router/src/Matches.tsx +++ b/packages/react-router/src/Matches.tsx @@ -1,5 +1,6 @@ import * as React from 'react' import warning from 'tiny-warning' +import { rootRouteId } from '@tanstack/router-core' import { CatchBoundary, ErrorComponent } from './CatchBoundary' import { useRouterState } from './useRouterState' import { useRouter } from './useRouter' @@ -12,6 +13,7 @@ import type { ValidateSelected, } from './structuralSharing' import type { + AnyRoute, AnyRouter, DeepPartial, Expand, @@ -41,10 +43,12 @@ declare module '@tanstack/router-core' { export function Matches() { const router = useRouter() + const rootRoute: AnyRoute = router.routesById[rootRouteId] - const pendingElement = router.options.defaultPendingComponent ? ( - - ) : null + const PendingComponent = + rootRoute.options.pendingComponent ?? router.options.defaultPendingComponent + + const pendingElement = PendingComponent ? : null // Do not render a root Suspense during SSR or hydrating from SSR const ResolvedSuspense = diff --git a/packages/react-router/tests/Matches.test.tsx b/packages/react-router/tests/Matches.test.tsx index 61fb2461bd7..3cb4f5c2b73 100644 --- a/packages/react-router/tests/Matches.test.tsx +++ b/packages/react-router/tests/Matches.test.tsx @@ -121,3 +121,23 @@ test('when filtering useMatches by loaderData', async () => { expect(await screen.findByText('Incorrect Matches -')).toBeInTheDocument() }) + +test('should show pendingComponent of root route', async () => { + const root = createRootRoute({ + pendingComponent: () =>
, + loader: async () => { + await new Promise((r) => setTimeout(r, 50)) + }, + component: () =>
, + }) + const router = createRouter({ + routeTree: root, + defaultPendingMs: 0, + defaultPendingComponent: () =>
default pending...
, + }) + + const rendered = render() + + expect(await rendered.findByTestId('root-pending')).toBeInTheDocument() + expect(await rendered.findByTestId('root-content')).toBeInTheDocument() +}) diff --git a/packages/solid-router/src/Matches.tsx b/packages/solid-router/src/Matches.tsx index f9fa1d34f7a..52bf981963d 100644 --- a/packages/solid-router/src/Matches.tsx +++ b/packages/solid-router/src/Matches.tsx @@ -1,5 +1,6 @@ import * as Solid from 'solid-js' import warning from 'tiny-warning' +import { rootRouteId } from '@tanstack/router-core' import { CatchBoundary, ErrorComponent } from './CatchBoundary' import { useRouterState } from './useRouterState' import { useRouter } from './useRouter' @@ -8,6 +9,7 @@ import { matchContext } from './matchContext' import { Match } from './Match' import { SafeFragment } from './SafeFragment' import type { + AnyRoute, AnyRouter, DeepPartial, Expand, @@ -44,16 +46,17 @@ export function Matches() { ? SafeFragment : Solid.Suspense + const rootRoute: () => AnyRoute = () => router.routesById[rootRouteId] + const PendingComponent = + rootRoute().options.pendingComponent ?? + router.options.defaultPendingComponent + const OptionalWrapper = router.options.InnerWrap || SafeFragment return ( - ) : null - } + fallback={PendingComponent ? : null} > {!router.isServer && } diff --git a/packages/solid-router/tests/Matches.test.tsx b/packages/solid-router/tests/Matches.test.tsx index 6f0f865a1bd..aed930bb0d8 100644 --- a/packages/solid-router/tests/Matches.test.tsx +++ b/packages/solid-router/tests/Matches.test.tsx @@ -221,3 +221,24 @@ test('Matches provides InnerWrap context to defaultPendingComponent', async () = const indexElem = await app.findByText('context-for-default-pending') expect(indexElem).toBeInTheDocument() }) + +test('should show pendingComponent of root route', async () => { + const root = createRootRoute({ + pendingComponent: () =>
, + loader: async () => { + await new Promise((r) => setTimeout(r, 50)) + }, + component: () =>
, + }) + + const router = createRouter({ + routeTree: root, + defaultPendingMs: 0, + defaultPendingComponent: () =>
default pending...
, + }) + + const rendered = render(() => ) + + expect(await rendered.findByTestId('root-pending')).toBeInTheDocument() + expect(await rendered.findByTestId('root-content')).toBeInTheDocument() +})