Skip to content

Commit

Permalink
fix: actually use pending component
Browse files Browse the repository at this point in the history
  • Loading branch information
tannerlinsley committed Aug 4, 2023
1 parent c97e0a7 commit 790b050
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 42 deletions.
98 changes: 69 additions & 29 deletions examples/react/quickstart/src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { StrictMode } from 'react'
import React, { StrictMode, Suspense } from 'react'
import ReactDOM from 'react-dom/client'
import {
Outlet,
Expand All @@ -7,45 +7,89 @@ import {
Router,
Route,
RootRoute,
lazyRouteComponent,
SyncRouteComponent,
} from '@tanstack/router'
import { TanStackRouterDevtools } from '@tanstack/router-devtools'

const rootRoute = new RootRoute({
component: () => (
<>
<div>
<Link to="/">Home</Link> <Link to="/about">About</Link>
</div>
<hr />
<Outlet />
<TanStackRouterDevtools />
</>
),
component: () => {
return (
<>
<div>
<Link to="/">Home</Link>
<br />
<Link to="/lazy-without-suspsense">Lazy without suspense</Link>
<br />
<Link to="/lazy-with-suspsense">Lazy with suspense</Link>
<br />
<Link to="/with-loader">With loader</Link>
</div>
<hr />
<Outlet />
</>
)
},
})

const indexRoute = new Route({
getParentRoute: () => rootRoute,
path: '/',
component: function Index() {
return (
<div>
<h3>Welcome Home!</h3>
</div>
)
return <h1>Hello world from "home"</h1>
},
})

const aboutRoute = new Route({
const lazyWithoutSuspense = new Route({
getParentRoute: () => rootRoute,
path: '/about',
component: function About() {
return <div>Hello from About!</div>
},
path: '/lazy-without-suspsense',
component: lazyRouteComponent(
() =>
new Promise<Record<string, SyncRouteComponent<any>>>((res) => {
setTimeout(() => {
res({
default: () => <h1>Hello world from "lazy-without-suspense"</h1>,
})
}, 1500)
}),
),
})

const routeTree = rootRoute.addChildren([indexRoute, aboutRoute])
const lazyWithSuspense = new Route({
getParentRoute: () => rootRoute,
path: '/lazy-with-suspsense',
component: lazyRouteComponent(
() =>
new Promise<Record<string, SyncRouteComponent<any>>>((res) => {
setTimeout(() => {
res({
default: () => <h1>Hello world from "lazy-with-suspense"</h1>,
})
}, 1500)
}),
),
pendingComponent: () => <h1>I'm loading</h1>,
wrapInSuspense: true,
})

const withLoader = new Route({
getParentRoute: () => rootRoute,
path: '/with-loader',
loader: () => new Promise((res) => setTimeout(res, 1000)),
component: () => <h1>Hello world from "with-laoder"</h1>,
wrapInSuspense: true,
pendingComponent: () => <h1>I'm loading</h1>,
})

const router = new Router({ routeTree })
const routeTree = rootRoute.addChildren([
indexRoute,
lazyWithoutSuspense,
lazyWithSuspense,
withLoader,
])

const router = new Router({
routeTree,
})

declare module '@tanstack/router' {
interface Register {
Expand All @@ -56,9 +100,5 @@ declare module '@tanstack/router' {
const rootElement = document.getElementById('app')!
if (!rootElement.innerHTML) {
const root = ReactDOM.createRoot(rootElement)
root.render(
<StrictMode>
<RouterProvider router={router} />
</StrictMode>,
)
root.render(<RouterProvider router={router} />)
}
1 change: 0 additions & 1 deletion packages/router/src/history.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ function createHistory(opts: {

const onUpdate = () => {
location = opts.getLocation()
console.log('onUpdate', location)
listeners.forEach((listener) => listener())
}

Expand Down
59 changes: 47 additions & 12 deletions packages/router/src/react.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -349,8 +349,21 @@ export function RouterProvider<
}

function Matches() {
const router = useRouter()

const matchIds = useRouterState({
select: (d) => d.matches.map((d) => d.id),
select: (d) => {
const hasPendingComponent = d.pendingMatches.some((d) => {
const route = router.getRoute(d.routeId as any)
return !!route?.options.pendingComponent
})

if (hasPendingComponent) {
return d.pendingMatches.map((d) => d.id)
}

return d.matches.map((d) => d.id)
},
})

return (
Expand Down Expand Up @@ -597,42 +610,64 @@ function Match({ matchIds }: { matchIds: string[] }) {

return (
<matchIdsContext.Provider value={matchIds}>
<ResolvedSuspenseBoundary fallback={<PendingComponent />}>
<ResolvedSuspenseBoundary
fallback={React.createElement(PendingComponent, {
useLoader: route.useLoader,
useMatch: route.useMatch,
useContext: route.useContext,
useSearch: route.useSearch,
useParams: route.useParams,
})}
>
<ResolvedCatchBoundary
key={route.id}
errorComponent={errorComponent}
onCatch={() => {
warning(false, `Error in route match: ${matchId}`)
}}
>
<MatchInner matchId={matchId} />
<MatchInner matchId={matchId} PendingComponent={PendingComponent} />
</ResolvedCatchBoundary>
</ResolvedSuspenseBoundary>
</matchIdsContext.Provider>
)
}

function MatchInner({ matchId }: { matchId: string }): any {
function MatchInner({
matchId,
PendingComponent,
}: {
matchId: string
PendingComponent: any
}): any {
const router = useRouter()

const match = useRouterState({
select: (d) =>
pick(d.matches.find((d) => d.id === matchId)!, [
'status',
'loadPromise',
'routeId',
'error',
]),
select: (d) => {
const match =
d.pendingMatches.find((d) => d.id === matchId) ||
d.matches.find((d) => d.id === matchId)

return pick(match!, ['status', 'loadPromise', 'routeId', 'error'])
},
})

console.log(match.status)

const route = router.getRoute(match.routeId)

if (match.status === 'error') {
throw match.error
}

if (match.status === 'pending') {
invariant(false, 'This should never happen')
return React.createElement(PendingComponent, {
useLoader: route.useLoader,
useMatch: route.useMatch,
useContext: route.useContext,
useSearch: route.useSearch,
useParams: route.useParams,
})
}

if (match.status === 'success') {
Expand Down
1 change: 1 addition & 0 deletions packages/router/src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1468,6 +1468,7 @@ export class Router<
): undefined | RouteMatch<TRoutesInfo, AnyRoute> => {
return (
this.state.matches.find((d) => d.id === id) ||
this.state.pendingMatches.find((d) => d.id === id) ||
this.state.preloadMatches[id]
)
}
Expand Down

0 comments on commit 790b050

Please sign in to comment.