@tanstack/react-router 1.120.4-alpha.12 → 1.120.4-alpha.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -233,6 +233,9 @@ const Outlet = React__namespace.memo(function OutletImpl() {
233
233
  return (_a = matches[index + 1]) == null ? void 0 : _a.id;
234
234
  }
235
235
  });
236
+ const pendingElement = router.options.defaultPendingComponent ? /* @__PURE__ */ jsxRuntime.jsx(router.options.defaultPendingComponent, {}) : null;
237
+ if (router.isShell)
238
+ return /* @__PURE__ */ jsxRuntime.jsx(React__namespace.Suspense, { fallback: pendingElement, children: /* @__PURE__ */ jsxRuntime.jsx(ShellInner, {}) });
236
239
  if (parentGlobalNotFound) {
237
240
  return renderRouteNotFound.renderRouteNotFound(router, route, void 0);
238
241
  }
@@ -240,12 +243,14 @@ const Outlet = React__namespace.memo(function OutletImpl() {
240
243
  return null;
241
244
  }
242
245
  const nextMatch = /* @__PURE__ */ jsxRuntime.jsx(Match, { matchId: childMatchId });
243
- const pendingElement = router.options.defaultPendingComponent ? /* @__PURE__ */ jsxRuntime.jsx(router.options.defaultPendingComponent, {}) : null;
244
246
  if (matchId === routerCore.rootRouteId) {
245
247
  return /* @__PURE__ */ jsxRuntime.jsx(React__namespace.Suspense, { fallback: pendingElement, children: nextMatch });
246
248
  }
247
249
  return nextMatch;
248
250
  });
251
+ function ShellInner() {
252
+ throw new Error("ShellBoundaryError");
253
+ }
249
254
  exports.Match = Match;
250
255
  exports.MatchInner = MatchInner;
251
256
  exports.Outlet = Outlet;
@@ -1 +1 @@
1
- {"version":3,"file":"Match.cjs","sources":["../../src/Match.tsx"],"sourcesContent":["import * as React from 'react'\nimport invariant from 'tiny-invariant'\nimport warning from 'tiny-warning'\nimport {\n createControlledPromise,\n getLocationChangeInfo,\n isNotFound,\n isRedirect,\n pick,\n rootRouteId,\n} from '@tanstack/router-core'\nimport { CatchBoundary, ErrorComponent } from './CatchBoundary'\nimport { useRouterState } from './useRouterState'\nimport { useRouter } from './useRouter'\nimport { CatchNotFound } from './not-found'\nimport { matchContext } from './matchContext'\nimport { SafeFragment } from './SafeFragment'\nimport { renderRouteNotFound } from './renderRouteNotFound'\nimport { ScrollRestoration } from './scroll-restoration'\nimport type { AnyRoute, ParsedLocation } from '@tanstack/router-core'\n\nexport const Match = React.memo(function MatchImpl({\n matchId,\n}: {\n matchId: string\n}) {\n const router = useRouter()\n const routeId = useRouterState({\n select: (s) => s.matches.find((d) => d.id === matchId)?.routeId as string,\n })\n\n invariant(\n routeId,\n `Could not find routeId for matchId \"${matchId}\". Please file an issue!`,\n )\n\n const route: AnyRoute = router.routesById[routeId]\n\n const PendingComponent =\n route.options.pendingComponent ?? router.options.defaultPendingComponent\n\n const pendingElement = PendingComponent ? <PendingComponent /> : null\n\n const routeErrorComponent =\n route.options.errorComponent ?? router.options.defaultErrorComponent\n\n const routeOnCatch = route.options.onCatch ?? router.options.defaultOnCatch\n\n const routeNotFoundComponent = route.isRoot\n ? // If it's the root route, use the globalNotFound option, with fallback to the notFoundRoute's component\n (route.options.notFoundComponent ??\n router.options.notFoundRoute?.options.component)\n : route.options.notFoundComponent\n\n const ResolvedSuspenseBoundary =\n // If we're on the root route, allow forcefully wrapping in suspense\n (!route.isRoot || route.options.wrapInSuspense) &&\n (route.options.wrapInSuspense ??\n PendingComponent ??\n (route.options.errorComponent as any)?.preload)\n ? React.Suspense\n : SafeFragment\n\n const ResolvedCatchBoundary = routeErrorComponent\n ? CatchBoundary\n : SafeFragment\n\n const ResolvedNotFoundBoundary = routeNotFoundComponent\n ? CatchNotFound\n : SafeFragment\n\n const resetKey = useRouterState({\n select: (s) => s.loadedAt,\n })\n\n const parentRouteId = useRouterState({\n select: (s) => {\n const index = s.matches.findIndex((d) => d.id === matchId)\n return s.matches[index - 1]?.routeId as string\n },\n })\n\n return (\n <>\n <matchContext.Provider value={matchId}>\n <ResolvedSuspenseBoundary fallback={pendingElement}>\n <ResolvedCatchBoundary\n getResetKey={() => resetKey}\n errorComponent={routeErrorComponent || ErrorComponent}\n onCatch={(error, errorInfo) => {\n // Forward not found errors (we don't want to show the error component for these)\n if (isNotFound(error)) throw error\n warning(false, `Error in route match: ${matchId}`)\n routeOnCatch?.(error, errorInfo)\n }}\n >\n <ResolvedNotFoundBoundary\n fallback={(error) => {\n // If the current not found handler doesn't exist or it has a\n // route ID which doesn't match the current route, rethrow the error\n if (\n !routeNotFoundComponent ||\n (error.routeId && error.routeId !== routeId) ||\n (!error.routeId && !route.isRoot)\n )\n throw error\n\n return React.createElement(routeNotFoundComponent, error as any)\n }}\n >\n <MatchInner matchId={matchId} />\n </ResolvedNotFoundBoundary>\n </ResolvedCatchBoundary>\n </ResolvedSuspenseBoundary>\n </matchContext.Provider>\n {parentRouteId === rootRouteId && router.options.scrollRestoration ? (\n <>\n <OnRendered />\n <ScrollRestoration />\n </>\n ) : null}\n </>\n )\n})\n\n// On Rendered can't happen above the root layout because it actually\n// renders a dummy dom element to track the rendered state of the app.\n// We render a script tag with a key that changes based on the current\n// location state.key. Also, because it's below the root layout, it\n// allows us to fire onRendered events even after a hydration mismatch\n// error that occurred above the root layout (like bad head/link tags,\n// which is common).\nfunction OnRendered() {\n const router = useRouter()\n\n const prevLocationRef = React.useRef<undefined | ParsedLocation<{}>>(\n undefined,\n )\n\n return (\n <script\n key={router.latestLocation.state.key}\n suppressHydrationWarning\n ref={(el) => {\n if (\n el &&\n (prevLocationRef.current === undefined ||\n prevLocationRef.current.href !== router.latestLocation.href)\n ) {\n router.emit({\n type: 'onRendered',\n ...getLocationChangeInfo(router.state),\n })\n prevLocationRef.current = router.latestLocation\n }\n }}\n />\n )\n}\n\nexport const MatchInner = React.memo(function MatchInnerImpl({\n matchId,\n}: {\n matchId: string\n}): any {\n const router = useRouter()\n\n const { match, key, routeId } = useRouterState({\n select: (s) => {\n const matchIndex = s.matches.findIndex((d) => d.id === matchId)\n const match = s.matches[matchIndex]!\n const routeId = match.routeId as string\n\n const remountFn =\n (router.routesById[routeId] as AnyRoute).options.remountDeps ??\n router.options.defaultRemountDeps\n const remountDeps = remountFn?.({\n routeId,\n loaderDeps: match.loaderDeps,\n params: match._strictParams,\n search: match._strictSearch,\n })\n const key = remountDeps ? JSON.stringify(remountDeps) : undefined\n\n return {\n key,\n routeId,\n match: pick(match, ['id', 'status', 'error']),\n }\n },\n structuralSharing: true as any,\n })\n\n const route = router.routesById[routeId] as AnyRoute\n\n const out = React.useMemo(() => {\n const Comp = route.options.component ?? router.options.defaultComponent\n if (Comp) {\n return <Comp key={key} />\n }\n return <Outlet />\n }, [key, route.options.component, router.options.defaultComponent])\n\n const RouteErrorComponent =\n (route.options.errorComponent ?? router.options.defaultErrorComponent) ||\n ErrorComponent\n\n if (match.status === 'notFound') {\n invariant(isNotFound(match.error), 'Expected a notFound error')\n return renderRouteNotFound(router, route, match.error)\n }\n\n if (match.status === 'redirected') {\n // Redirects should be handled by the router transition. If we happen to\n // encounter a redirect here, it's a bug. Let's warn, but render nothing.\n invariant(isRedirect(match.error), 'Expected a redirect error')\n\n // warning(\n // false,\n // 'Tried to render a redirected route match! This is a weird circumstance, please file an issue!',\n // )\n throw router.getMatch(match.id)?.loadPromise\n }\n\n if (match.status === 'error') {\n // If we're on the server, we need to use React's new and super\n // wonky api for throwing errors from a server side render inside\n // of a suspense boundary. This is the only way to get\n // renderToPipeableStream to not hang indefinitely.\n // We'll serialize the error and rethrow it on the client.\n if (router.isServer) {\n return (\n <RouteErrorComponent\n error={match.error as any}\n reset={undefined as any}\n info={{\n componentStack: '',\n }}\n />\n )\n }\n\n throw match.error\n }\n\n if (match.status === 'pending') {\n // We're pending, and if we have a minPendingMs, we need to wait for it\n const pendingMinMs =\n route.options.pendingMinMs ?? router.options.defaultPendingMinMs\n\n if (pendingMinMs && !router.getMatch(match.id)?.minPendingPromise) {\n // Create a promise that will resolve after the minPendingMs\n if (!router.isServer) {\n const minPendingPromise = createControlledPromise<void>()\n\n Promise.resolve().then(() => {\n router.updateMatch(match.id, (prev) => ({\n ...prev,\n minPendingPromise,\n }))\n })\n\n setTimeout(() => {\n minPendingPromise.resolve()\n\n // We've handled the minPendingPromise, so we can delete it\n router.updateMatch(match.id, (prev) => ({\n ...prev,\n minPendingPromise: undefined,\n }))\n }, pendingMinMs)\n }\n }\n throw router.getMatch(match.id)?.loadPromise\n }\n\n return out\n})\n\nexport const Outlet = React.memo(function OutletImpl() {\n const router = useRouter()\n const matchId = React.useContext(matchContext)\n const routeId = useRouterState({\n select: (s) => s.matches.find((d) => d.id === matchId)?.routeId as string,\n })\n\n const route = router.routesById[routeId]!\n\n const parentGlobalNotFound = useRouterState({\n select: (s) => {\n const matches = s.matches\n const parentMatch = matches.find((d) => d.id === matchId)\n invariant(\n parentMatch,\n `Could not find parent match for matchId \"${matchId}\"`,\n )\n return parentMatch.globalNotFound\n },\n })\n\n const childMatchId = useRouterState({\n select: (s) => {\n const matches = s.matches\n const index = matches.findIndex((d) => d.id === matchId)\n return matches[index + 1]?.id\n },\n })\n\n if (parentGlobalNotFound) {\n return renderRouteNotFound(router, route, undefined)\n }\n\n if (!childMatchId) {\n return null\n }\n\n const nextMatch = <Match matchId={childMatchId} />\n\n const pendingElement = router.options.defaultPendingComponent ? (\n <router.options.defaultPendingComponent />\n ) : null\n\n if (matchId === rootRouteId) {\n return (\n <React.Suspense fallback={pendingElement}>{nextMatch}</React.Suspense>\n )\n }\n\n return nextMatch\n})\n"],"names":["React","useRouter","useRouterState","_a","jsx","SafeFragment","CatchBoundary","CatchNotFound","jsxs","Fragment","matchContext","ErrorComponent","isNotFound","rootRouteId","ScrollRestoration","getLocationChangeInfo","match","routeId","key","pick","renderRouteNotFound","isRedirect","createControlledPromise"],"mappings":"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"}
1
+ {"version":3,"file":"Match.cjs","sources":["../../src/Match.tsx"],"sourcesContent":["import * as React from 'react'\nimport invariant from 'tiny-invariant'\nimport warning from 'tiny-warning'\nimport {\n createControlledPromise,\n getLocationChangeInfo,\n isNotFound,\n isRedirect,\n pick,\n rootRouteId,\n} from '@tanstack/router-core'\nimport { CatchBoundary, ErrorComponent } from './CatchBoundary'\nimport { useRouterState } from './useRouterState'\nimport { useRouter } from './useRouter'\nimport { CatchNotFound } from './not-found'\nimport { matchContext } from './matchContext'\nimport { SafeFragment } from './SafeFragment'\nimport { renderRouteNotFound } from './renderRouteNotFound'\nimport { ScrollRestoration } from './scroll-restoration'\nimport type { AnyRoute, ParsedLocation } from '@tanstack/router-core'\n\nexport const Match = React.memo(function MatchImpl({\n matchId,\n}: {\n matchId: string\n}) {\n const router = useRouter()\n const routeId = useRouterState({\n select: (s) => s.matches.find((d) => d.id === matchId)?.routeId as string,\n })\n\n invariant(\n routeId,\n `Could not find routeId for matchId \"${matchId}\". Please file an issue!`,\n )\n\n const route: AnyRoute = router.routesById[routeId]\n\n const PendingComponent =\n route.options.pendingComponent ?? router.options.defaultPendingComponent\n\n const pendingElement = PendingComponent ? <PendingComponent /> : null\n\n const routeErrorComponent =\n route.options.errorComponent ?? router.options.defaultErrorComponent\n\n const routeOnCatch = route.options.onCatch ?? router.options.defaultOnCatch\n\n const routeNotFoundComponent = route.isRoot\n ? // If it's the root route, use the globalNotFound option, with fallback to the notFoundRoute's component\n (route.options.notFoundComponent ??\n router.options.notFoundRoute?.options.component)\n : route.options.notFoundComponent\n\n const ResolvedSuspenseBoundary =\n // If we're on the root route, allow forcefully wrapping in suspense\n (!route.isRoot || route.options.wrapInSuspense) &&\n (route.options.wrapInSuspense ??\n PendingComponent ??\n (route.options.errorComponent as any)?.preload)\n ? React.Suspense\n : SafeFragment\n\n const ResolvedCatchBoundary = routeErrorComponent\n ? CatchBoundary\n : SafeFragment\n\n const ResolvedNotFoundBoundary = routeNotFoundComponent\n ? CatchNotFound\n : SafeFragment\n\n const resetKey = useRouterState({\n select: (s) => s.loadedAt,\n })\n\n const parentRouteId = useRouterState({\n select: (s) => {\n const index = s.matches.findIndex((d) => d.id === matchId)\n return s.matches[index - 1]?.routeId as string\n },\n })\n\n return (\n <>\n <matchContext.Provider value={matchId}>\n <ResolvedSuspenseBoundary fallback={pendingElement}>\n <ResolvedCatchBoundary\n getResetKey={() => resetKey}\n errorComponent={routeErrorComponent || ErrorComponent}\n onCatch={(error, errorInfo) => {\n // Forward not found errors (we don't want to show the error component for these)\n if (isNotFound(error)) throw error\n warning(false, `Error in route match: ${matchId}`)\n routeOnCatch?.(error, errorInfo)\n }}\n >\n <ResolvedNotFoundBoundary\n fallback={(error) => {\n // If the current not found handler doesn't exist or it has a\n // route ID which doesn't match the current route, rethrow the error\n if (\n !routeNotFoundComponent ||\n (error.routeId && error.routeId !== routeId) ||\n (!error.routeId && !route.isRoot)\n )\n throw error\n\n return React.createElement(routeNotFoundComponent, error as any)\n }}\n >\n <MatchInner matchId={matchId} />\n </ResolvedNotFoundBoundary>\n </ResolvedCatchBoundary>\n </ResolvedSuspenseBoundary>\n </matchContext.Provider>\n {parentRouteId === rootRouteId && router.options.scrollRestoration ? (\n <>\n <OnRendered />\n <ScrollRestoration />\n </>\n ) : null}\n </>\n )\n})\n\n// On Rendered can't happen above the root layout because it actually\n// renders a dummy dom element to track the rendered state of the app.\n// We render a script tag with a key that changes based on the current\n// location state.key. Also, because it's below the root layout, it\n// allows us to fire onRendered events even after a hydration mismatch\n// error that occurred above the root layout (like bad head/link tags,\n// which is common).\nfunction OnRendered() {\n const router = useRouter()\n\n const prevLocationRef = React.useRef<undefined | ParsedLocation<{}>>(\n undefined,\n )\n\n return (\n <script\n key={router.latestLocation.state.key}\n suppressHydrationWarning\n ref={(el) => {\n if (\n el &&\n (prevLocationRef.current === undefined ||\n prevLocationRef.current.href !== router.latestLocation.href)\n ) {\n router.emit({\n type: 'onRendered',\n ...getLocationChangeInfo(router.state),\n })\n prevLocationRef.current = router.latestLocation\n }\n }}\n />\n )\n}\n\nexport const MatchInner = React.memo(function MatchInnerImpl({\n matchId,\n}: {\n matchId: string\n}): any {\n const router = useRouter()\n\n const { match, key, routeId } = useRouterState({\n select: (s) => {\n const matchIndex = s.matches.findIndex((d) => d.id === matchId)\n const match = s.matches[matchIndex]!\n const routeId = match.routeId as string\n\n const remountFn =\n (router.routesById[routeId] as AnyRoute).options.remountDeps ??\n router.options.defaultRemountDeps\n const remountDeps = remountFn?.({\n routeId,\n loaderDeps: match.loaderDeps,\n params: match._strictParams,\n search: match._strictSearch,\n })\n const key = remountDeps ? JSON.stringify(remountDeps) : undefined\n\n return {\n key,\n routeId,\n match: pick(match, ['id', 'status', 'error']),\n }\n },\n structuralSharing: true as any,\n })\n\n const route = router.routesById[routeId] as AnyRoute\n\n const out = React.useMemo(() => {\n const Comp = route.options.component ?? router.options.defaultComponent\n if (Comp) {\n return <Comp key={key} />\n }\n return <Outlet />\n }, [key, route.options.component, router.options.defaultComponent])\n\n const RouteErrorComponent =\n (route.options.errorComponent ?? router.options.defaultErrorComponent) ||\n ErrorComponent\n\n if (match.status === 'notFound') {\n invariant(isNotFound(match.error), 'Expected a notFound error')\n return renderRouteNotFound(router, route, match.error)\n }\n\n if (match.status === 'redirected') {\n // Redirects should be handled by the router transition. If we happen to\n // encounter a redirect here, it's a bug. Let's warn, but render nothing.\n invariant(isRedirect(match.error), 'Expected a redirect error')\n\n // warning(\n // false,\n // 'Tried to render a redirected route match! This is a weird circumstance, please file an issue!',\n // )\n throw router.getMatch(match.id)?.loadPromise\n }\n\n if (match.status === 'error') {\n // If we're on the server, we need to use React's new and super\n // wonky api for throwing errors from a server side render inside\n // of a suspense boundary. This is the only way to get\n // renderToPipeableStream to not hang indefinitely.\n // We'll serialize the error and rethrow it on the client.\n if (router.isServer) {\n return (\n <RouteErrorComponent\n error={match.error as any}\n reset={undefined as any}\n info={{\n componentStack: '',\n }}\n />\n )\n }\n\n throw match.error\n }\n\n if (match.status === 'pending') {\n // We're pending, and if we have a minPendingMs, we need to wait for it\n const pendingMinMs =\n route.options.pendingMinMs ?? router.options.defaultPendingMinMs\n\n if (pendingMinMs && !router.getMatch(match.id)?.minPendingPromise) {\n // Create a promise that will resolve after the minPendingMs\n if (!router.isServer) {\n const minPendingPromise = createControlledPromise<void>()\n\n Promise.resolve().then(() => {\n router.updateMatch(match.id, (prev) => ({\n ...prev,\n minPendingPromise,\n }))\n })\n\n setTimeout(() => {\n minPendingPromise.resolve()\n\n // We've handled the minPendingPromise, so we can delete it\n router.updateMatch(match.id, (prev) => ({\n ...prev,\n minPendingPromise: undefined,\n }))\n }, pendingMinMs)\n }\n }\n throw router.getMatch(match.id)?.loadPromise\n }\n\n return out\n})\n\nexport const Outlet = React.memo(function OutletImpl() {\n const router = useRouter()\n const matchId = React.useContext(matchContext)\n const routeId = useRouterState({\n select: (s) => s.matches.find((d) => d.id === matchId)?.routeId as string,\n })\n\n const route = router.routesById[routeId]!\n\n const parentGlobalNotFound = useRouterState({\n select: (s) => {\n const matches = s.matches\n const parentMatch = matches.find((d) => d.id === matchId)\n invariant(\n parentMatch,\n `Could not find parent match for matchId \"${matchId}\"`,\n )\n return parentMatch.globalNotFound\n },\n })\n\n const childMatchId = useRouterState({\n select: (s) => {\n const matches = s.matches\n const index = matches.findIndex((d) => d.id === matchId)\n return matches[index + 1]?.id\n },\n })\n\n const pendingElement = router.options.defaultPendingComponent ? (\n <router.options.defaultPendingComponent />\n ) : null\n\n if (router.isShell)\n return (\n <React.Suspense fallback={pendingElement}>\n <ShellInner />\n </React.Suspense>\n )\n\n if (parentGlobalNotFound) {\n return renderRouteNotFound(router, route, undefined)\n }\n\n if (!childMatchId) {\n return null\n }\n\n const nextMatch = <Match matchId={childMatchId} />\n\n if (matchId === rootRouteId) {\n return (\n <React.Suspense fallback={pendingElement}>{nextMatch}</React.Suspense>\n )\n }\n\n return nextMatch\n})\n\nfunction ShellInner(): React.ReactElement {\n throw new Error('ShellBoundaryError')\n}\n"],"names":["React","useRouter","useRouterState","_a","jsx","SafeFragment","CatchBoundary","CatchNotFound","jsxs","Fragment","matchContext","ErrorComponent","isNotFound","rootRouteId","ScrollRestoration","getLocationChangeInfo","match","routeId","key","pick","renderRouteNotFound","isRedirect","createControlledPromise"],"mappings":"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"}
package/dist/esm/Match.js CHANGED
@@ -214,6 +214,9 @@ const Outlet = React.memo(function OutletImpl() {
214
214
  return (_a = matches[index + 1]) == null ? void 0 : _a.id;
215
215
  }
216
216
  });
217
+ const pendingElement = router.options.defaultPendingComponent ? /* @__PURE__ */ jsx(router.options.defaultPendingComponent, {}) : null;
218
+ if (router.isShell)
219
+ return /* @__PURE__ */ jsx(React.Suspense, { fallback: pendingElement, children: /* @__PURE__ */ jsx(ShellInner, {}) });
217
220
  if (parentGlobalNotFound) {
218
221
  return renderRouteNotFound(router, route, void 0);
219
222
  }
@@ -221,12 +224,14 @@ const Outlet = React.memo(function OutletImpl() {
221
224
  return null;
222
225
  }
223
226
  const nextMatch = /* @__PURE__ */ jsx(Match, { matchId: childMatchId });
224
- const pendingElement = router.options.defaultPendingComponent ? /* @__PURE__ */ jsx(router.options.defaultPendingComponent, {}) : null;
225
227
  if (matchId === rootRouteId) {
226
228
  return /* @__PURE__ */ jsx(React.Suspense, { fallback: pendingElement, children: nextMatch });
227
229
  }
228
230
  return nextMatch;
229
231
  });
232
+ function ShellInner() {
233
+ throw new Error("ShellBoundaryError");
234
+ }
230
235
  export {
231
236
  Match,
232
237
  MatchInner,
@@ -1 +1 @@
1
- {"version":3,"file":"Match.js","sources":["../../src/Match.tsx"],"sourcesContent":["import * as React from 'react'\nimport invariant from 'tiny-invariant'\nimport warning from 'tiny-warning'\nimport {\n createControlledPromise,\n getLocationChangeInfo,\n isNotFound,\n isRedirect,\n pick,\n rootRouteId,\n} from '@tanstack/router-core'\nimport { CatchBoundary, ErrorComponent } from './CatchBoundary'\nimport { useRouterState } from './useRouterState'\nimport { useRouter } from './useRouter'\nimport { CatchNotFound } from './not-found'\nimport { matchContext } from './matchContext'\nimport { SafeFragment } from './SafeFragment'\nimport { renderRouteNotFound } from './renderRouteNotFound'\nimport { ScrollRestoration } from './scroll-restoration'\nimport type { AnyRoute, ParsedLocation } from '@tanstack/router-core'\n\nexport const Match = React.memo(function MatchImpl({\n matchId,\n}: {\n matchId: string\n}) {\n const router = useRouter()\n const routeId = useRouterState({\n select: (s) => s.matches.find((d) => d.id === matchId)?.routeId as string,\n })\n\n invariant(\n routeId,\n `Could not find routeId for matchId \"${matchId}\". Please file an issue!`,\n )\n\n const route: AnyRoute = router.routesById[routeId]\n\n const PendingComponent =\n route.options.pendingComponent ?? router.options.defaultPendingComponent\n\n const pendingElement = PendingComponent ? <PendingComponent /> : null\n\n const routeErrorComponent =\n route.options.errorComponent ?? router.options.defaultErrorComponent\n\n const routeOnCatch = route.options.onCatch ?? router.options.defaultOnCatch\n\n const routeNotFoundComponent = route.isRoot\n ? // If it's the root route, use the globalNotFound option, with fallback to the notFoundRoute's component\n (route.options.notFoundComponent ??\n router.options.notFoundRoute?.options.component)\n : route.options.notFoundComponent\n\n const ResolvedSuspenseBoundary =\n // If we're on the root route, allow forcefully wrapping in suspense\n (!route.isRoot || route.options.wrapInSuspense) &&\n (route.options.wrapInSuspense ??\n PendingComponent ??\n (route.options.errorComponent as any)?.preload)\n ? React.Suspense\n : SafeFragment\n\n const ResolvedCatchBoundary = routeErrorComponent\n ? CatchBoundary\n : SafeFragment\n\n const ResolvedNotFoundBoundary = routeNotFoundComponent\n ? CatchNotFound\n : SafeFragment\n\n const resetKey = useRouterState({\n select: (s) => s.loadedAt,\n })\n\n const parentRouteId = useRouterState({\n select: (s) => {\n const index = s.matches.findIndex((d) => d.id === matchId)\n return s.matches[index - 1]?.routeId as string\n },\n })\n\n return (\n <>\n <matchContext.Provider value={matchId}>\n <ResolvedSuspenseBoundary fallback={pendingElement}>\n <ResolvedCatchBoundary\n getResetKey={() => resetKey}\n errorComponent={routeErrorComponent || ErrorComponent}\n onCatch={(error, errorInfo) => {\n // Forward not found errors (we don't want to show the error component for these)\n if (isNotFound(error)) throw error\n warning(false, `Error in route match: ${matchId}`)\n routeOnCatch?.(error, errorInfo)\n }}\n >\n <ResolvedNotFoundBoundary\n fallback={(error) => {\n // If the current not found handler doesn't exist or it has a\n // route ID which doesn't match the current route, rethrow the error\n if (\n !routeNotFoundComponent ||\n (error.routeId && error.routeId !== routeId) ||\n (!error.routeId && !route.isRoot)\n )\n throw error\n\n return React.createElement(routeNotFoundComponent, error as any)\n }}\n >\n <MatchInner matchId={matchId} />\n </ResolvedNotFoundBoundary>\n </ResolvedCatchBoundary>\n </ResolvedSuspenseBoundary>\n </matchContext.Provider>\n {parentRouteId === rootRouteId && router.options.scrollRestoration ? (\n <>\n <OnRendered />\n <ScrollRestoration />\n </>\n ) : null}\n </>\n )\n})\n\n// On Rendered can't happen above the root layout because it actually\n// renders a dummy dom element to track the rendered state of the app.\n// We render a script tag with a key that changes based on the current\n// location state.key. Also, because it's below the root layout, it\n// allows us to fire onRendered events even after a hydration mismatch\n// error that occurred above the root layout (like bad head/link tags,\n// which is common).\nfunction OnRendered() {\n const router = useRouter()\n\n const prevLocationRef = React.useRef<undefined | ParsedLocation<{}>>(\n undefined,\n )\n\n return (\n <script\n key={router.latestLocation.state.key}\n suppressHydrationWarning\n ref={(el) => {\n if (\n el &&\n (prevLocationRef.current === undefined ||\n prevLocationRef.current.href !== router.latestLocation.href)\n ) {\n router.emit({\n type: 'onRendered',\n ...getLocationChangeInfo(router.state),\n })\n prevLocationRef.current = router.latestLocation\n }\n }}\n />\n )\n}\n\nexport const MatchInner = React.memo(function MatchInnerImpl({\n matchId,\n}: {\n matchId: string\n}): any {\n const router = useRouter()\n\n const { match, key, routeId } = useRouterState({\n select: (s) => {\n const matchIndex = s.matches.findIndex((d) => d.id === matchId)\n const match = s.matches[matchIndex]!\n const routeId = match.routeId as string\n\n const remountFn =\n (router.routesById[routeId] as AnyRoute).options.remountDeps ??\n router.options.defaultRemountDeps\n const remountDeps = remountFn?.({\n routeId,\n loaderDeps: match.loaderDeps,\n params: match._strictParams,\n search: match._strictSearch,\n })\n const key = remountDeps ? JSON.stringify(remountDeps) : undefined\n\n return {\n key,\n routeId,\n match: pick(match, ['id', 'status', 'error']),\n }\n },\n structuralSharing: true as any,\n })\n\n const route = router.routesById[routeId] as AnyRoute\n\n const out = React.useMemo(() => {\n const Comp = route.options.component ?? router.options.defaultComponent\n if (Comp) {\n return <Comp key={key} />\n }\n return <Outlet />\n }, [key, route.options.component, router.options.defaultComponent])\n\n const RouteErrorComponent =\n (route.options.errorComponent ?? router.options.defaultErrorComponent) ||\n ErrorComponent\n\n if (match.status === 'notFound') {\n invariant(isNotFound(match.error), 'Expected a notFound error')\n return renderRouteNotFound(router, route, match.error)\n }\n\n if (match.status === 'redirected') {\n // Redirects should be handled by the router transition. If we happen to\n // encounter a redirect here, it's a bug. Let's warn, but render nothing.\n invariant(isRedirect(match.error), 'Expected a redirect error')\n\n // warning(\n // false,\n // 'Tried to render a redirected route match! This is a weird circumstance, please file an issue!',\n // )\n throw router.getMatch(match.id)?.loadPromise\n }\n\n if (match.status === 'error') {\n // If we're on the server, we need to use React's new and super\n // wonky api for throwing errors from a server side render inside\n // of a suspense boundary. This is the only way to get\n // renderToPipeableStream to not hang indefinitely.\n // We'll serialize the error and rethrow it on the client.\n if (router.isServer) {\n return (\n <RouteErrorComponent\n error={match.error as any}\n reset={undefined as any}\n info={{\n componentStack: '',\n }}\n />\n )\n }\n\n throw match.error\n }\n\n if (match.status === 'pending') {\n // We're pending, and if we have a minPendingMs, we need to wait for it\n const pendingMinMs =\n route.options.pendingMinMs ?? router.options.defaultPendingMinMs\n\n if (pendingMinMs && !router.getMatch(match.id)?.minPendingPromise) {\n // Create a promise that will resolve after the minPendingMs\n if (!router.isServer) {\n const minPendingPromise = createControlledPromise<void>()\n\n Promise.resolve().then(() => {\n router.updateMatch(match.id, (prev) => ({\n ...prev,\n minPendingPromise,\n }))\n })\n\n setTimeout(() => {\n minPendingPromise.resolve()\n\n // We've handled the minPendingPromise, so we can delete it\n router.updateMatch(match.id, (prev) => ({\n ...prev,\n minPendingPromise: undefined,\n }))\n }, pendingMinMs)\n }\n }\n throw router.getMatch(match.id)?.loadPromise\n }\n\n return out\n})\n\nexport const Outlet = React.memo(function OutletImpl() {\n const router = useRouter()\n const matchId = React.useContext(matchContext)\n const routeId = useRouterState({\n select: (s) => s.matches.find((d) => d.id === matchId)?.routeId as string,\n })\n\n const route = router.routesById[routeId]!\n\n const parentGlobalNotFound = useRouterState({\n select: (s) => {\n const matches = s.matches\n const parentMatch = matches.find((d) => d.id === matchId)\n invariant(\n parentMatch,\n `Could not find parent match for matchId \"${matchId}\"`,\n )\n return parentMatch.globalNotFound\n },\n })\n\n const childMatchId = useRouterState({\n select: (s) => {\n const matches = s.matches\n const index = matches.findIndex((d) => d.id === matchId)\n return matches[index + 1]?.id\n },\n })\n\n if (parentGlobalNotFound) {\n return renderRouteNotFound(router, route, undefined)\n }\n\n if (!childMatchId) {\n return null\n }\n\n const nextMatch = <Match matchId={childMatchId} />\n\n const pendingElement = router.options.defaultPendingComponent ? (\n <router.options.defaultPendingComponent />\n ) : null\n\n if (matchId === rootRouteId) {\n return (\n <React.Suspense fallback={pendingElement}>{nextMatch}</React.Suspense>\n )\n }\n\n return nextMatch\n})\n"],"names":["_a","match","routeId","key"],"mappings":"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"}
1
+ {"version":3,"file":"Match.js","sources":["../../src/Match.tsx"],"sourcesContent":["import * as React from 'react'\nimport invariant from 'tiny-invariant'\nimport warning from 'tiny-warning'\nimport {\n createControlledPromise,\n getLocationChangeInfo,\n isNotFound,\n isRedirect,\n pick,\n rootRouteId,\n} from '@tanstack/router-core'\nimport { CatchBoundary, ErrorComponent } from './CatchBoundary'\nimport { useRouterState } from './useRouterState'\nimport { useRouter } from './useRouter'\nimport { CatchNotFound } from './not-found'\nimport { matchContext } from './matchContext'\nimport { SafeFragment } from './SafeFragment'\nimport { renderRouteNotFound } from './renderRouteNotFound'\nimport { ScrollRestoration } from './scroll-restoration'\nimport type { AnyRoute, ParsedLocation } from '@tanstack/router-core'\n\nexport const Match = React.memo(function MatchImpl({\n matchId,\n}: {\n matchId: string\n}) {\n const router = useRouter()\n const routeId = useRouterState({\n select: (s) => s.matches.find((d) => d.id === matchId)?.routeId as string,\n })\n\n invariant(\n routeId,\n `Could not find routeId for matchId \"${matchId}\". Please file an issue!`,\n )\n\n const route: AnyRoute = router.routesById[routeId]\n\n const PendingComponent =\n route.options.pendingComponent ?? router.options.defaultPendingComponent\n\n const pendingElement = PendingComponent ? <PendingComponent /> : null\n\n const routeErrorComponent =\n route.options.errorComponent ?? router.options.defaultErrorComponent\n\n const routeOnCatch = route.options.onCatch ?? router.options.defaultOnCatch\n\n const routeNotFoundComponent = route.isRoot\n ? // If it's the root route, use the globalNotFound option, with fallback to the notFoundRoute's component\n (route.options.notFoundComponent ??\n router.options.notFoundRoute?.options.component)\n : route.options.notFoundComponent\n\n const ResolvedSuspenseBoundary =\n // If we're on the root route, allow forcefully wrapping in suspense\n (!route.isRoot || route.options.wrapInSuspense) &&\n (route.options.wrapInSuspense ??\n PendingComponent ??\n (route.options.errorComponent as any)?.preload)\n ? React.Suspense\n : SafeFragment\n\n const ResolvedCatchBoundary = routeErrorComponent\n ? CatchBoundary\n : SafeFragment\n\n const ResolvedNotFoundBoundary = routeNotFoundComponent\n ? CatchNotFound\n : SafeFragment\n\n const resetKey = useRouterState({\n select: (s) => s.loadedAt,\n })\n\n const parentRouteId = useRouterState({\n select: (s) => {\n const index = s.matches.findIndex((d) => d.id === matchId)\n return s.matches[index - 1]?.routeId as string\n },\n })\n\n return (\n <>\n <matchContext.Provider value={matchId}>\n <ResolvedSuspenseBoundary fallback={pendingElement}>\n <ResolvedCatchBoundary\n getResetKey={() => resetKey}\n errorComponent={routeErrorComponent || ErrorComponent}\n onCatch={(error, errorInfo) => {\n // Forward not found errors (we don't want to show the error component for these)\n if (isNotFound(error)) throw error\n warning(false, `Error in route match: ${matchId}`)\n routeOnCatch?.(error, errorInfo)\n }}\n >\n <ResolvedNotFoundBoundary\n fallback={(error) => {\n // If the current not found handler doesn't exist or it has a\n // route ID which doesn't match the current route, rethrow the error\n if (\n !routeNotFoundComponent ||\n (error.routeId && error.routeId !== routeId) ||\n (!error.routeId && !route.isRoot)\n )\n throw error\n\n return React.createElement(routeNotFoundComponent, error as any)\n }}\n >\n <MatchInner matchId={matchId} />\n </ResolvedNotFoundBoundary>\n </ResolvedCatchBoundary>\n </ResolvedSuspenseBoundary>\n </matchContext.Provider>\n {parentRouteId === rootRouteId && router.options.scrollRestoration ? (\n <>\n <OnRendered />\n <ScrollRestoration />\n </>\n ) : null}\n </>\n )\n})\n\n// On Rendered can't happen above the root layout because it actually\n// renders a dummy dom element to track the rendered state of the app.\n// We render a script tag with a key that changes based on the current\n// location state.key. Also, because it's below the root layout, it\n// allows us to fire onRendered events even after a hydration mismatch\n// error that occurred above the root layout (like bad head/link tags,\n// which is common).\nfunction OnRendered() {\n const router = useRouter()\n\n const prevLocationRef = React.useRef<undefined | ParsedLocation<{}>>(\n undefined,\n )\n\n return (\n <script\n key={router.latestLocation.state.key}\n suppressHydrationWarning\n ref={(el) => {\n if (\n el &&\n (prevLocationRef.current === undefined ||\n prevLocationRef.current.href !== router.latestLocation.href)\n ) {\n router.emit({\n type: 'onRendered',\n ...getLocationChangeInfo(router.state),\n })\n prevLocationRef.current = router.latestLocation\n }\n }}\n />\n )\n}\n\nexport const MatchInner = React.memo(function MatchInnerImpl({\n matchId,\n}: {\n matchId: string\n}): any {\n const router = useRouter()\n\n const { match, key, routeId } = useRouterState({\n select: (s) => {\n const matchIndex = s.matches.findIndex((d) => d.id === matchId)\n const match = s.matches[matchIndex]!\n const routeId = match.routeId as string\n\n const remountFn =\n (router.routesById[routeId] as AnyRoute).options.remountDeps ??\n router.options.defaultRemountDeps\n const remountDeps = remountFn?.({\n routeId,\n loaderDeps: match.loaderDeps,\n params: match._strictParams,\n search: match._strictSearch,\n })\n const key = remountDeps ? JSON.stringify(remountDeps) : undefined\n\n return {\n key,\n routeId,\n match: pick(match, ['id', 'status', 'error']),\n }\n },\n structuralSharing: true as any,\n })\n\n const route = router.routesById[routeId] as AnyRoute\n\n const out = React.useMemo(() => {\n const Comp = route.options.component ?? router.options.defaultComponent\n if (Comp) {\n return <Comp key={key} />\n }\n return <Outlet />\n }, [key, route.options.component, router.options.defaultComponent])\n\n const RouteErrorComponent =\n (route.options.errorComponent ?? router.options.defaultErrorComponent) ||\n ErrorComponent\n\n if (match.status === 'notFound') {\n invariant(isNotFound(match.error), 'Expected a notFound error')\n return renderRouteNotFound(router, route, match.error)\n }\n\n if (match.status === 'redirected') {\n // Redirects should be handled by the router transition. If we happen to\n // encounter a redirect here, it's a bug. Let's warn, but render nothing.\n invariant(isRedirect(match.error), 'Expected a redirect error')\n\n // warning(\n // false,\n // 'Tried to render a redirected route match! This is a weird circumstance, please file an issue!',\n // )\n throw router.getMatch(match.id)?.loadPromise\n }\n\n if (match.status === 'error') {\n // If we're on the server, we need to use React's new and super\n // wonky api for throwing errors from a server side render inside\n // of a suspense boundary. This is the only way to get\n // renderToPipeableStream to not hang indefinitely.\n // We'll serialize the error and rethrow it on the client.\n if (router.isServer) {\n return (\n <RouteErrorComponent\n error={match.error as any}\n reset={undefined as any}\n info={{\n componentStack: '',\n }}\n />\n )\n }\n\n throw match.error\n }\n\n if (match.status === 'pending') {\n // We're pending, and if we have a minPendingMs, we need to wait for it\n const pendingMinMs =\n route.options.pendingMinMs ?? router.options.defaultPendingMinMs\n\n if (pendingMinMs && !router.getMatch(match.id)?.minPendingPromise) {\n // Create a promise that will resolve after the minPendingMs\n if (!router.isServer) {\n const minPendingPromise = createControlledPromise<void>()\n\n Promise.resolve().then(() => {\n router.updateMatch(match.id, (prev) => ({\n ...prev,\n minPendingPromise,\n }))\n })\n\n setTimeout(() => {\n minPendingPromise.resolve()\n\n // We've handled the minPendingPromise, so we can delete it\n router.updateMatch(match.id, (prev) => ({\n ...prev,\n minPendingPromise: undefined,\n }))\n }, pendingMinMs)\n }\n }\n throw router.getMatch(match.id)?.loadPromise\n }\n\n return out\n})\n\nexport const Outlet = React.memo(function OutletImpl() {\n const router = useRouter()\n const matchId = React.useContext(matchContext)\n const routeId = useRouterState({\n select: (s) => s.matches.find((d) => d.id === matchId)?.routeId as string,\n })\n\n const route = router.routesById[routeId]!\n\n const parentGlobalNotFound = useRouterState({\n select: (s) => {\n const matches = s.matches\n const parentMatch = matches.find((d) => d.id === matchId)\n invariant(\n parentMatch,\n `Could not find parent match for matchId \"${matchId}\"`,\n )\n return parentMatch.globalNotFound\n },\n })\n\n const childMatchId = useRouterState({\n select: (s) => {\n const matches = s.matches\n const index = matches.findIndex((d) => d.id === matchId)\n return matches[index + 1]?.id\n },\n })\n\n const pendingElement = router.options.defaultPendingComponent ? (\n <router.options.defaultPendingComponent />\n ) : null\n\n if (router.isShell)\n return (\n <React.Suspense fallback={pendingElement}>\n <ShellInner />\n </React.Suspense>\n )\n\n if (parentGlobalNotFound) {\n return renderRouteNotFound(router, route, undefined)\n }\n\n if (!childMatchId) {\n return null\n }\n\n const nextMatch = <Match matchId={childMatchId} />\n\n if (matchId === rootRouteId) {\n return (\n <React.Suspense fallback={pendingElement}>{nextMatch}</React.Suspense>\n )\n }\n\n return nextMatch\n})\n\nfunction ShellInner(): React.ReactElement {\n throw new Error('ShellBoundaryError')\n}\n"],"names":["_a","match","routeId","key"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/react-router",
3
- "version": "1.120.4-alpha.12",
3
+ "version": "1.120.4-alpha.15",
4
4
  "description": "Modern and scalable routing for React applications",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -54,7 +54,7 @@
54
54
  "tiny-invariant": "^1.3.3",
55
55
  "tiny-warning": "^1.0.3",
56
56
  "@tanstack/history": "1.120.4-alpha.1",
57
- "@tanstack/router-core": "1.120.4-alpha.12"
57
+ "@tanstack/router-core": "1.120.4-alpha.15"
58
58
  },
59
59
  "devDependencies": {
60
60
  "@testing-library/jest-dom": "^6.6.3",
package/src/Match.tsx CHANGED
@@ -306,6 +306,17 @@ export const Outlet = React.memo(function OutletImpl() {
306
306
  },
307
307
  })
308
308
 
309
+ const pendingElement = router.options.defaultPendingComponent ? (
310
+ <router.options.defaultPendingComponent />
311
+ ) : null
312
+
313
+ if (router.isShell)
314
+ return (
315
+ <React.Suspense fallback={pendingElement}>
316
+ <ShellInner />
317
+ </React.Suspense>
318
+ )
319
+
309
320
  if (parentGlobalNotFound) {
310
321
  return renderRouteNotFound(router, route, undefined)
311
322
  }
@@ -316,10 +327,6 @@ export const Outlet = React.memo(function OutletImpl() {
316
327
 
317
328
  const nextMatch = <Match matchId={childMatchId} />
318
329
 
319
- const pendingElement = router.options.defaultPendingComponent ? (
320
- <router.options.defaultPendingComponent />
321
- ) : null
322
-
323
330
  if (matchId === rootRouteId) {
324
331
  return (
325
332
  <React.Suspense fallback={pendingElement}>{nextMatch}</React.Suspense>
@@ -328,3 +335,7 @@ export const Outlet = React.memo(function OutletImpl() {
328
335
 
329
336
  return nextMatch
330
337
  })
338
+
339
+ function ShellInner(): React.ReactElement {
340
+ throw new Error('ShellBoundaryError')
341
+ }