@tanstack/react-router 1.51.9 → 1.52.1

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.
@@ -110,8 +110,8 @@ const MatchInner = React__namespace.memo(function MatchInnerImpl({
110
110
  const route = router.routesById[routeId];
111
111
  const out = React__namespace.useMemo(() => {
112
112
  const Comp = route.options.component ?? router.options.defaultComponent;
113
- return Comp ? /* @__PURE__ */ jsxRuntime.jsx(Comp, {}, routeId) : /* @__PURE__ */ jsxRuntime.jsx(Outlet, {});
114
- }, [routeId, route.options.component, router.options.defaultComponent]);
113
+ return Comp ? /* @__PURE__ */ jsxRuntime.jsx(Comp, {}) : /* @__PURE__ */ jsxRuntime.jsx(Outlet, {});
114
+ }, [route.options.component, router.options.defaultComponent]);
115
115
  const RouteErrorComponent = (route.options.errorComponent ?? router.options.defaultErrorComponent) || CatchBoundary.ErrorComponent;
116
116
  if (match.status === "notFound") {
117
117
  let error;
@@ -1 +1 @@
1
- {"version":3,"file":"Match.cjs","sources":["../../src/Match.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport invariant from 'tiny-invariant'\nimport warning from 'tiny-warning'\nimport { CatchBoundary, ErrorComponent } from './CatchBoundary'\nimport { useRouterState } from './useRouterState'\nimport { useRouter } from './useRouter'\nimport { createControlledPromise, pick } from './utils'\nimport { CatchNotFound, isNotFound } from './not-found'\nimport { isRedirect } from './redirects'\nimport { matchContext } from './matchContext'\nimport { defaultDeserializeError, isServerSideError } from './isServerSideError'\nimport { SafeFragment } from './SafeFragment'\nimport { renderRouteNotFound } from './renderRouteNotFound'\nimport { rootRouteId } from './root'\nimport type { AnyRoute } from './route'\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 return (\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 )\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, matchIndex, 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 return {\n routeId,\n matchIndex,\n match: pick(match, ['id', 'status', 'error', 'loadPromise']),\n }\n },\n })\n\n const route = router.routesById[routeId]!\n\n const out = React.useMemo(() => {\n const Comp = route.options.component ?? router.options.defaultComponent\n return Comp ? <Comp key={routeId} /> : <Outlet />\n }, [routeId, route.options.component, router.options.defaultComponent])\n\n // function useChangedDiff(value: any) {\n // const ref = React.useRef(value)\n // const changed = ref.current !== value\n // if (changed) {\n // console.log(\n // 'Changed:',\n // value,\n // Object.fromEntries(\n // Object.entries(value).filter(\n // ([key, val]) => val !== ref.current[key],\n // ),\n // ),\n // )\n // }\n // ref.current = value\n // }\n\n // useChangedDiff(match)\n\n const RouteErrorComponent =\n (route.options.errorComponent ?? router.options.defaultErrorComponent) ||\n ErrorComponent\n\n if (match.status === 'notFound') {\n let error: unknown\n if (isServerSideError(match.error)) {\n const deserializeError =\n router.options.errorSerializer?.deserialize ?? defaultDeserializeError\n\n error = deserializeError(match.error.data)\n } else {\n error = match.error\n }\n\n invariant(isNotFound(error), 'Expected a notFound error')\n\n return renderRouteNotFound(router, route, 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 match.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}\n info={{\n componentStack: '',\n }}\n />\n )\n }\n\n if (isServerSideError(match.error)) {\n const deserializeError =\n router.options.errorSerializer?.deserialize ?? defaultDeserializeError\n throw deserializeError(match.error.data)\n } else {\n throw match.error\n }\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 match.loadPromise\n }\n\n return (\n <>\n {out}\n {router.AfterEachMatch ? (\n <router.AfterEachMatch match={match} matchIndex={matchIndex} />\n ) : null}\n </>\n )\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 {\n parentGlobalNotFound: parentMatch.globalNotFound,\n }\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":["matchIndex","match","routeId"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkBO;AAA4C;AAEnD;;AAGE;AACA;AAA+B;;AACd;AAAyC;AAAA;AAG1D;AAAA;AACE;AAC8C;AAG1C;AAEN;AAGA;AAEA;AAGA;AAEA;AAAqC;AAAA;AAGK;AAGpC;AAAA;AAAA;AAOA;AAEA;AAIA;AAIN;AAAgC;AACb;AAIjB;AAEI;AAAC;AAAA;AACoB;AACoB;AAGjC;AACI;AACR;AAAsB;AACxB;AAEA;AAAC;AAAA;AAKK;AAIM;AAED;AAAwD;AACjE;AAE8B;AAAA;AAChC;AAAA;AAKV;AAEO;AAAsD;AAE7D;;AAGE;AAEA;AAAsD;AAE5CA;AACAC;AACN;AACO;AAAA;AACLC;AACAF;AAC2D;AAAA;AAE/D;AAGI;AAEA;AACJ;AACA;AAA+C;AAsBjD;AAII;AACE;AACA;AACF;AAGQ;AAAiC;AAEzC;AAAc;AAGN;AAEH;AAAwC;AAG7C;AAGF;AAMA;AAAY;AAGV;AAMF;AAEI;AAAA;AAAC;AAAA;AACc;AACP;AACY;AAClB;AAAA;AAAA;AAKF;AACF;AAEM;AAAiC;AAEvC;AAAY;AACd;AAGE;AAEF;AAGA;AAEM;AACF;AAEQ;AACN;AAAwC;AACnC;AACH;AACA;AAGJ;AACE;AAGA;AAAwC;AACnC;AACgB;AACnB;AACW;AACjB;AAEF;AAAY;AAGd;AAEK;AAAA;AAGG;AAGV;AAEO;AACL;AACM;AACN;AAA+B;;AACd;AAAyC;AAAA;AAGpD;AAEA;AAA0C;AAE5C;AACA;AACA;AAAA;AACE;AACmD;AAE9C;AAAA;AAC6B;AAAA;AAEtC;AAGF;AAAoC;;AAEhC;AACA;AACO;AAAoB;AAC7B;AAGF;AACS;AAA4C;AAGrD;AACS;AAAA;AAGT;AAEM;AAIN;AACE;AACuD;AAIlD;AACT;;;;"}
1
+ {"version":3,"file":"Match.cjs","sources":["../../src/Match.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport invariant from 'tiny-invariant'\nimport warning from 'tiny-warning'\nimport { CatchBoundary, ErrorComponent } from './CatchBoundary'\nimport { useRouterState } from './useRouterState'\nimport { useRouter } from './useRouter'\nimport { createControlledPromise, pick } from './utils'\nimport { CatchNotFound, isNotFound } from './not-found'\nimport { isRedirect } from './redirects'\nimport { matchContext } from './matchContext'\nimport { defaultDeserializeError, isServerSideError } from './isServerSideError'\nimport { SafeFragment } from './SafeFragment'\nimport { renderRouteNotFound } from './renderRouteNotFound'\nimport { rootRouteId } from './root'\nimport type { AnyRoute } from './route'\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 return (\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 )\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, matchIndex, 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 return {\n routeId,\n matchIndex,\n match: pick(match, ['id', 'status', 'error', 'loadPromise']),\n }\n },\n })\n\n const route = router.routesById[routeId]!\n\n const out = React.useMemo(() => {\n const Comp = route.options.component ?? router.options.defaultComponent\n return Comp ? <Comp /> : <Outlet />\n }, [route.options.component, router.options.defaultComponent])\n\n // function useChangedDiff(value: any) {\n // const ref = React.useRef(value)\n // const changed = ref.current !== value\n // if (changed) {\n // console.log(\n // 'Changed:',\n // value,\n // Object.fromEntries(\n // Object.entries(value).filter(\n // ([key, val]) => val !== ref.current[key],\n // ),\n // ),\n // )\n // }\n // ref.current = value\n // }\n\n // useChangedDiff(match)\n\n const RouteErrorComponent =\n (route.options.errorComponent ?? router.options.defaultErrorComponent) ||\n ErrorComponent\n\n if (match.status === 'notFound') {\n let error: unknown\n if (isServerSideError(match.error)) {\n const deserializeError =\n router.options.errorSerializer?.deserialize ?? defaultDeserializeError\n\n error = deserializeError(match.error.data)\n } else {\n error = match.error\n }\n\n invariant(isNotFound(error), 'Expected a notFound error')\n\n return renderRouteNotFound(router, route, 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 match.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}\n info={{\n componentStack: '',\n }}\n />\n )\n }\n\n if (isServerSideError(match.error)) {\n const deserializeError =\n router.options.errorSerializer?.deserialize ?? defaultDeserializeError\n throw deserializeError(match.error.data)\n } else {\n throw match.error\n }\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 match.loadPromise\n }\n\n return (\n <>\n {out}\n {router.AfterEachMatch ? (\n <router.AfterEachMatch match={match} matchIndex={matchIndex} />\n ) : null}\n </>\n )\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 {\n parentGlobalNotFound: parentMatch.globalNotFound,\n }\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":["matchIndex","match","routeId"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkBO;AAA4C;AAEnD;;AAGE;AACA;AAA+B;;AACd;AAAyC;AAAA;AAG1D;AAAA;AACE;AAC8C;AAG1C;AAEN;AAGA;AAEA;AAGA;AAEA;AAAqC;AAAA;AAGK;AAGpC;AAAA;AAAA;AAOA;AAEA;AAIA;AAIN;AAAgC;AACb;AAIjB;AAEI;AAAC;AAAA;AACoB;AACoB;AAGjC;AACI;AACR;AAAsB;AACxB;AAEA;AAAC;AAAA;AAKK;AAIM;AAED;AAAwD;AACjE;AAE8B;AAAA;AAChC;AAAA;AAKV;AAEO;AAAsD;AAE7D;;AAGE;AAEA;AAAsD;AAE5CA;AACAC;AACN;AACO;AAAA;AACLC;AACAF;AAC2D;AAAA;AAE/D;AAGI;AAEA;AACJ;AACA;AAAiC;AAsBnC;AAII;AACE;AACA;AACF;AAGQ;AAAiC;AAEzC;AAAc;AAGN;AAEH;AAAwC;AAG7C;AAGF;AAMA;AAAY;AAGV;AAMF;AAEI;AAAA;AAAC;AAAA;AACc;AACP;AACY;AAClB;AAAA;AAAA;AAKF;AACF;AAEM;AAAiC;AAEvC;AAAY;AACd;AAGE;AAEF;AAGA;AAEM;AACF;AAEQ;AACN;AAAwC;AACnC;AACH;AACA;AAGJ;AACE;AAGA;AAAwC;AACnC;AACgB;AACnB;AACW;AACjB;AAEF;AAAY;AAGd;AAEK;AAAA;AAGG;AAGV;AAEO;AACL;AACM;AACN;AAA+B;;AACd;AAAyC;AAAA;AAGpD;AAEA;AAA0C;AAE5C;AACA;AACA;AAAA;AACE;AACmD;AAE9C;AAAA;AAC6B;AAAA;AAEtC;AAGF;AAAoC;;AAEhC;AACA;AACO;AAAoB;AAC7B;AAGF;AACS;AAA4C;AAGrD;AACS;AAAA;AAGT;AAEM;AAIN;AACE;AACuD;AAIlD;AACT;;;;"}
package/dist/esm/Match.js CHANGED
@@ -91,8 +91,8 @@ const MatchInner = React.memo(function MatchInnerImpl({
91
91
  const route = router.routesById[routeId];
92
92
  const out = React.useMemo(() => {
93
93
  const Comp = route.options.component ?? router.options.defaultComponent;
94
- return Comp ? /* @__PURE__ */ jsx(Comp, {}, routeId) : /* @__PURE__ */ jsx(Outlet, {});
95
- }, [routeId, route.options.component, router.options.defaultComponent]);
94
+ return Comp ? /* @__PURE__ */ jsx(Comp, {}) : /* @__PURE__ */ jsx(Outlet, {});
95
+ }, [route.options.component, router.options.defaultComponent]);
96
96
  const RouteErrorComponent = (route.options.errorComponent ?? router.options.defaultErrorComponent) || ErrorComponent;
97
97
  if (match.status === "notFound") {
98
98
  let error;
@@ -1 +1 @@
1
- {"version":3,"file":"Match.js","sources":["../../src/Match.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport invariant from 'tiny-invariant'\nimport warning from 'tiny-warning'\nimport { CatchBoundary, ErrorComponent } from './CatchBoundary'\nimport { useRouterState } from './useRouterState'\nimport { useRouter } from './useRouter'\nimport { createControlledPromise, pick } from './utils'\nimport { CatchNotFound, isNotFound } from './not-found'\nimport { isRedirect } from './redirects'\nimport { matchContext } from './matchContext'\nimport { defaultDeserializeError, isServerSideError } from './isServerSideError'\nimport { SafeFragment } from './SafeFragment'\nimport { renderRouteNotFound } from './renderRouteNotFound'\nimport { rootRouteId } from './root'\nimport type { AnyRoute } from './route'\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 return (\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 )\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, matchIndex, 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 return {\n routeId,\n matchIndex,\n match: pick(match, ['id', 'status', 'error', 'loadPromise']),\n }\n },\n })\n\n const route = router.routesById[routeId]!\n\n const out = React.useMemo(() => {\n const Comp = route.options.component ?? router.options.defaultComponent\n return Comp ? <Comp key={routeId} /> : <Outlet />\n }, [routeId, route.options.component, router.options.defaultComponent])\n\n // function useChangedDiff(value: any) {\n // const ref = React.useRef(value)\n // const changed = ref.current !== value\n // if (changed) {\n // console.log(\n // 'Changed:',\n // value,\n // Object.fromEntries(\n // Object.entries(value).filter(\n // ([key, val]) => val !== ref.current[key],\n // ),\n // ),\n // )\n // }\n // ref.current = value\n // }\n\n // useChangedDiff(match)\n\n const RouteErrorComponent =\n (route.options.errorComponent ?? router.options.defaultErrorComponent) ||\n ErrorComponent\n\n if (match.status === 'notFound') {\n let error: unknown\n if (isServerSideError(match.error)) {\n const deserializeError =\n router.options.errorSerializer?.deserialize ?? defaultDeserializeError\n\n error = deserializeError(match.error.data)\n } else {\n error = match.error\n }\n\n invariant(isNotFound(error), 'Expected a notFound error')\n\n return renderRouteNotFound(router, route, 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 match.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}\n info={{\n componentStack: '',\n }}\n />\n )\n }\n\n if (isServerSideError(match.error)) {\n const deserializeError =\n router.options.errorSerializer?.deserialize ?? defaultDeserializeError\n throw deserializeError(match.error.data)\n } else {\n throw match.error\n }\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 match.loadPromise\n }\n\n return (\n <>\n {out}\n {router.AfterEachMatch ? (\n <router.AfterEachMatch match={match} matchIndex={matchIndex} />\n ) : null}\n </>\n )\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 {\n parentGlobalNotFound: parentMatch.globalNotFound,\n }\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":["matchIndex","match","routeId"],"mappings":";;;;;;;;;;;;;;;;AAkBO;AAA4C;AAEnD;;AAGE;AACA;AAA+B;;AACd;AAAyC;AAAA;AAG1D;AAAA;AACE;AAC8C;AAG1C;AAEN;AAGA;AAEA;AAGA;AAEA;AAAqC;AAAA;AAGK;AAGpC;AAAA;AAAA;AAOA;AAEA;AAIA;AAIN;AAAgC;AACb;AAIjB;AAEI;AAAC;AAAA;AACoB;AACoB;AAGjC;AACI;AACR;AAAsB;AACxB;AAEA;AAAC;AAAA;AAKK;AAIM;AAED;AAAwD;AACjE;AAE8B;AAAA;AAChC;AAAA;AAKV;AAEO;AAAsD;AAE7D;;AAGE;AAEA;AAAsD;AAE5CA;AACAC;AACN;AACO;AAAA;AACLC;AACAF;AAC2D;AAAA;AAE/D;AAGI;AAEA;AACJ;AACA;AAA+C;AAsBjD;AAII;AACE;AACA;AACF;AAGQ;AAAiC;AAEzC;AAAc;AAGN;AAEH;AAAwC;AAG7C;AAGF;AAMA;AAAY;AAGV;AAMF;AAEI;AAAA;AAAC;AAAA;AACc;AACP;AACY;AAClB;AAAA;AAAA;AAKF;AACF;AAEM;AAAiC;AAEvC;AAAY;AACd;AAGE;AAEF;AAGA;AAEM;AACF;AAEQ;AACN;AAAwC;AACnC;AACH;AACA;AAGJ;AACE;AAGA;AAAwC;AACnC;AACgB;AACnB;AACW;AACjB;AAEF;AAAY;AAGd;AAEK;AAAA;AAGG;AAGV;AAEO;AACL;AACM;AACN;AAA+B;;AACd;AAAyC;AAAA;AAGpD;AAEA;AAA0C;AAE5C;AACA;AACA;AAAA;AACE;AACmD;AAE9C;AAAA;AAC6B;AAAA;AAEtC;AAGF;AAAoC;;AAEhC;AACA;AACO;AAAoB;AAC7B;AAGF;AACS;AAA4C;AAGrD;AACS;AAAA;AAGT;AAEM;AAIN;AACE;AACuD;AAIlD;AACT;;;;;;"}
1
+ {"version":3,"file":"Match.js","sources":["../../src/Match.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport invariant from 'tiny-invariant'\nimport warning from 'tiny-warning'\nimport { CatchBoundary, ErrorComponent } from './CatchBoundary'\nimport { useRouterState } from './useRouterState'\nimport { useRouter } from './useRouter'\nimport { createControlledPromise, pick } from './utils'\nimport { CatchNotFound, isNotFound } from './not-found'\nimport { isRedirect } from './redirects'\nimport { matchContext } from './matchContext'\nimport { defaultDeserializeError, isServerSideError } from './isServerSideError'\nimport { SafeFragment } from './SafeFragment'\nimport { renderRouteNotFound } from './renderRouteNotFound'\nimport { rootRouteId } from './root'\nimport type { AnyRoute } from './route'\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 return (\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 )\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, matchIndex, 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 return {\n routeId,\n matchIndex,\n match: pick(match, ['id', 'status', 'error', 'loadPromise']),\n }\n },\n })\n\n const route = router.routesById[routeId]!\n\n const out = React.useMemo(() => {\n const Comp = route.options.component ?? router.options.defaultComponent\n return Comp ? <Comp /> : <Outlet />\n }, [route.options.component, router.options.defaultComponent])\n\n // function useChangedDiff(value: any) {\n // const ref = React.useRef(value)\n // const changed = ref.current !== value\n // if (changed) {\n // console.log(\n // 'Changed:',\n // value,\n // Object.fromEntries(\n // Object.entries(value).filter(\n // ([key, val]) => val !== ref.current[key],\n // ),\n // ),\n // )\n // }\n // ref.current = value\n // }\n\n // useChangedDiff(match)\n\n const RouteErrorComponent =\n (route.options.errorComponent ?? router.options.defaultErrorComponent) ||\n ErrorComponent\n\n if (match.status === 'notFound') {\n let error: unknown\n if (isServerSideError(match.error)) {\n const deserializeError =\n router.options.errorSerializer?.deserialize ?? defaultDeserializeError\n\n error = deserializeError(match.error.data)\n } else {\n error = match.error\n }\n\n invariant(isNotFound(error), 'Expected a notFound error')\n\n return renderRouteNotFound(router, route, 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 match.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}\n info={{\n componentStack: '',\n }}\n />\n )\n }\n\n if (isServerSideError(match.error)) {\n const deserializeError =\n router.options.errorSerializer?.deserialize ?? defaultDeserializeError\n throw deserializeError(match.error.data)\n } else {\n throw match.error\n }\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 match.loadPromise\n }\n\n return (\n <>\n {out}\n {router.AfterEachMatch ? (\n <router.AfterEachMatch match={match} matchIndex={matchIndex} />\n ) : null}\n </>\n )\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 {\n parentGlobalNotFound: parentMatch.globalNotFound,\n }\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":["matchIndex","match","routeId"],"mappings":";;;;;;;;;;;;;;;;AAkBO;AAA4C;AAEnD;;AAGE;AACA;AAA+B;;AACd;AAAyC;AAAA;AAG1D;AAAA;AACE;AAC8C;AAG1C;AAEN;AAGA;AAEA;AAGA;AAEA;AAAqC;AAAA;AAGK;AAGpC;AAAA;AAAA;AAOA;AAEA;AAIA;AAIN;AAAgC;AACb;AAIjB;AAEI;AAAC;AAAA;AACoB;AACoB;AAGjC;AACI;AACR;AAAsB;AACxB;AAEA;AAAC;AAAA;AAKK;AAIM;AAED;AAAwD;AACjE;AAE8B;AAAA;AAChC;AAAA;AAKV;AAEO;AAAsD;AAE7D;;AAGE;AAEA;AAAsD;AAE5CA;AACAC;AACN;AACO;AAAA;AACLC;AACAF;AAC2D;AAAA;AAE/D;AAGI;AAEA;AACJ;AACA;AAAiC;AAsBnC;AAII;AACE;AACA;AACF;AAGQ;AAAiC;AAEzC;AAAc;AAGN;AAEH;AAAwC;AAG7C;AAGF;AAMA;AAAY;AAGV;AAMF;AAEI;AAAA;AAAC;AAAA;AACc;AACP;AACY;AAClB;AAAA;AAAA;AAKF;AACF;AAEM;AAAiC;AAEvC;AAAY;AACd;AAGE;AAEF;AAGA;AAEM;AACF;AAEQ;AACN;AAAwC;AACnC;AACH;AACA;AAGJ;AACE;AAGA;AAAwC;AACnC;AACgB;AACnB;AACW;AACjB;AAEF;AAAY;AAGd;AAEK;AAAA;AAGG;AAGV;AAEO;AACL;AACM;AACN;AAA+B;;AACd;AAAyC;AAAA;AAGpD;AAEA;AAA0C;AAE5C;AACA;AACA;AAAA;AACE;AACmD;AAE9C;AAAA;AAC6B;AAAA;AAEtC;AAGF;AAAoC;;AAEhC;AACA;AACO;AAAoB;AAC7B;AAGF;AACS;AAA4C;AAGrD;AACS;AAAA;AAGT;AAEM;AAIN;AACE;AACuD;AAIlD;AACT;;;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/react-router",
3
- "version": "1.51.9",
3
+ "version": "1.52.1",
4
4
  "description": "Modern and scalable routing for React applications",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
package/src/Match.tsx CHANGED
@@ -129,8 +129,8 @@ export const MatchInner = React.memo(function MatchInnerImpl({
129
129
 
130
130
  const out = React.useMemo(() => {
131
131
  const Comp = route.options.component ?? router.options.defaultComponent
132
- return Comp ? <Comp key={routeId} /> : <Outlet />
133
- }, [routeId, route.options.component, router.options.defaultComponent])
132
+ return Comp ? <Comp /> : <Outlet />
133
+ }, [route.options.component, router.options.defaultComponent])
134
134
 
135
135
  // function useChangedDiff(value: any) {
136
136
  // const ref = React.useRef(value)