Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions packages/react-router/src/Matches.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type {
ValidateSelected,
} from './structuralSharing'
import type {
AnyRoute,
AnyRouter,
DeepPartial,
Expand,
Expand Down Expand Up @@ -41,10 +42,12 @@ declare module '@tanstack/router-core' {

export function Matches() {
const router = useRouter()
const rootRoute: AnyRoute = router.routesById['__root__']
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need to be defensive here and type this as AnyRoute | undefined. I think a __root__ route must always exist ...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please use rootRouteId from @tanstack/router-core instead of __root__

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and to answer your question, the answer is probably not, since a root route must always be present, but if it helps silence typescript then a ! assertion or a throw Error should be fine.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done: 74a3835


const pendingElement = router.options.defaultPendingComponent ? (
<router.options.defaultPendingComponent />
) : null
const PendingComponent =
rootRoute.options.pendingComponent ?? router.options.defaultPendingComponent

const pendingElement = PendingComponent ? <PendingComponent /> : null

// Do not render a root Suspense during SSR or hydrating from SSR
const ResolvedSuspense =
Expand Down
24 changes: 24 additions & 0 deletions packages/react-router/tests/Matches.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,27 @@ 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: () => <div>root pending...</div>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please use data-testid and getByTestId or similar methods instead of looking for textual matches

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done: 6fc6e2b

loader: async () => {
await new Promise((r) => setTimeout(r, 50))
},
})
const index = createRoute({
getParentRoute: () => root,
path: '/',
component: () => <div>index route</div>,
})
const router = createRouter({
routeTree: root.addChildren([index]),
defaultPendingMs: 0,
defaultPendingComponent: () => <div>default pending...</div>,
})

const rendered = render(<RouterProvider router={router} />)

expect(await rendered.findByText('root pending...')).toBeInTheDocument()
expect(await rendered.findByText('index route')).toBeInTheDocument()
})
12 changes: 7 additions & 5 deletions packages/solid-router/src/Matches.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { matchContext } from './matchContext'
import { Match } from './Match'
import { SafeFragment } from './SafeFragment'
import type {
AnyRoute,
AnyRouter,
DeepPartial,
Expand,
Expand Down Expand Up @@ -44,16 +45,17 @@ export function Matches() {
? SafeFragment
: Solid.Suspense

const rootRoute: () => AnyRoute = () => router.routesById['__root__']
const PendingComponent =
rootRoute().options.pendingComponent ??
router.options.defaultPendingComponent

const OptionalWrapper = router.options.InnerWrap || SafeFragment

return (
<OptionalWrapper>
<ResolvedSuspense
fallback={
router.options.defaultPendingComponent ? (
<router.options.defaultPendingComponent />
) : null
}
fallback={PendingComponent ? <PendingComponent /> : null}
>
{!router.isServer && <Transitioner />}
<MatchesInner />
Expand Down
24 changes: 24 additions & 0 deletions packages/solid-router/tests/Matches.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -221,3 +221,27 @@ 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: () => <div>root pending...</div>,
loader: async () => {
await new Promise((r) => setTimeout(r, 50))
},
})
const index = createRoute({
getParentRoute: () => root,
path: '/',
component: () => <div>index route</div>,
})
const router = createRouter({
routeTree: root.addChildren([index]),
defaultPendingMs: 0,
defaultPendingComponent: () => <div>default pending...</div>,
})

const rendered = render(() => <RouterProvider router={router} />)

expect(await rendered.findByText('root pending...')).toBeInTheDocument()
expect(await rendered.findByText('index route')).toBeInTheDocument()
})
Loading