Skip to content

Commit 148e35e

Browse files
committed
Change approach
1 parent a2956c7 commit 148e35e

File tree

2 files changed

+28
-41
lines changed

2 files changed

+28
-41
lines changed

packages/react-router/lib/dom/ssr/single-fetch.tsx

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ import type { DataRouteMatch } from "../../context";
2424

2525
export const SingleFetchRedirectSymbol = Symbol("SingleFetchRedirect");
2626

27+
class SingleFetchNoResultError extends Error {}
28+
2729
export type SingleFetchRedirectResult = {
2830
redirect: string;
2931
status: number;
@@ -466,16 +468,29 @@ async function singleFetchLoaderNavigationStrategy(
466468

467469
await resolvePromise;
468470

469-
// Capture any middleware errors from routes that weren't actually fetching
470-
// data, these will be bubbled by the router in `processRouteLoaderData`
471+
// If a middleware threw on the way down, we won't have data for our requested
472+
// loaders and they'll resolve to `SingleFetchNoResultError` results. If this
473+
// happens, take the highest error we find in our results (which is a middleware
474+
// error if no loaders ever ran), and assign to these missing routes and let
475+
// the router bubble accordingly
476+
let middlewareError: unknown;
471477
let fetchedData = await singleFetchDfd.promise;
472478
if ("routes" in fetchedData) {
473-
Object.entries(fetchedData.routes).forEach(([routeId, result]) => {
474-
if ("error" in result && results[routeId]?.type !== "error") {
475-
results[routeId] = {
476-
type: "error",
477-
result: result.error,
478-
};
479+
for (let match of args.matches) {
480+
if (match.route.id in fetchedData.routes) {
481+
let routeResult = fetchedData.routes[match.route.id];
482+
if ("error" in routeResult) {
483+
middlewareError = routeResult.error;
484+
break;
485+
}
486+
}
487+
}
488+
}
489+
490+
if (middlewareError !== undefined) {
491+
Array.from(routesParams.values()).forEach((routeId) => {
492+
if (results[routeId].result instanceof SingleFetchNoResultError) {
493+
results[routeId].result = middlewareError;
479494
}
480495
});
481496
}
@@ -709,7 +724,9 @@ function unwrapSingleFetchResult(
709724

710725
let routeResult = result.routes[routeId];
711726
if (routeResult == null) {
712-
throw new Error(`No result found for routeId "${routeId}"`);
727+
throw new SingleFetchNoResultError(
728+
`No result found for routeId "${routeId}"`
729+
);
713730
} else if ("error" in routeResult) {
714731
throw routeResult.error;
715732
} else if ("data" in routeResult) {

packages/react-router/lib/router/router.ts

Lines changed: 2 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3635,26 +3635,11 @@ export function createStaticHandler(
36353635
)?.route.id || routeId
36363636
).route.id;
36373637

3638-
// If we errored in the top-down middleware, stub in `undefined`
3639-
// for all loaders the front end is expecting results for
3640-
let loaderData: RouterState["loaderData"] = {};
3641-
if (!isMutationMethod(request.method)) {
3642-
matches
3643-
.filter((m) =>
3644-
filterMatchesToLoad
3645-
? filterMatchesToLoad(m)
3646-
: m.route.loader
3647-
)
3648-
.forEach((m) => {
3649-
loaderData[m.route.id] = undefined;
3650-
});
3651-
}
3652-
36533638
return respond({
36543639
matches: matches!,
36553640
location,
36563641
basename,
3657-
loaderData,
3642+
loaderData: {},
36583643
actionData: null,
36593644
errors: {
36603645
[boundaryRouteId]: error,
@@ -6056,22 +6041,7 @@ function processRouteLoaderData(
60566041
if (skipLoaderErrorBubbling) {
60576042
errors[id] = error;
60586043
} else {
6059-
// Bubble the error to the proper error boundary by looking upwards from
6060-
// the highest route that defines a `loader` but doesn't currently have
6061-
// any `loaderData`. This situation can happen if a middleware throws
6062-
// on the way down and thus a loader never executes for a given route.
6063-
// If such a route doesn't exist, then we just look upwards from the
6064-
// throwing route. Prefer higher error values if lower errors bubble to
6065-
// the same boundary
6066-
let highestLoaderRouteWithoutData = currentLoaderData
6067-
? matches.find(
6068-
(m) => m.route.loader && !(m.route.id in currentLoaderData)
6069-
)
6070-
: undefined;
6071-
let boundaryMatch = findNearestBoundary(
6072-
matches,
6073-
highestLoaderRouteWithoutData?.route.id || id
6074-
);
6044+
let boundaryMatch = findNearestBoundary(matches, id);
60756045
if (errors[boundaryMatch.route.id] == null) {
60766046
errors[boundaryMatch.route.id] = error;
60776047
}

0 commit comments

Comments
 (0)