Skip to content

Commit 2709b84

Browse files
authoredAug 11, 2023
Fix a race-condition with loader/action-thrown errors on route.lazy routes (#10778)
* Fix a race-condition with loader/action-thrown errors on route.lazy routes * Unit tests
1 parent 8b3559a commit 2709b84

File tree

3 files changed

+54
-1
lines changed

3 files changed

+54
-1
lines changed
 

‎.changeset/route-lazy-race.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@remix-run/router": patch
3+
---
4+
5+
Fix a race-condition with loader/action-thrown errors on route.lazy routes

‎packages/router/__tests__/router-test.ts

+39
Original file line numberDiff line numberDiff line change
@@ -13737,6 +13737,45 @@ describe("a router", () => {
1373713737
);
1373813738
consoleWarn.mockReset();
1373913739
});
13740+
13741+
it("handles errors thrown from static loaders before lazy has completed", async () => {
13742+
let consoleWarn = jest.spyOn(console, "warn");
13743+
let t = setup({
13744+
routes: [
13745+
{
13746+
id: "root",
13747+
path: "/",
13748+
children: [
13749+
{
13750+
id: "lazy",
13751+
path: "lazy",
13752+
loader: true,
13753+
lazy: true,
13754+
},
13755+
],
13756+
},
13757+
],
13758+
});
13759+
13760+
let A = await t.navigate("/lazy");
13761+
13762+
await A.loaders.lazy.reject("STATIC LOADER ERROR");
13763+
expect(t.router.state.navigation.state).toBe("loading");
13764+
13765+
// We shouldn't bubble the loader error until after this resolves
13766+
// so we know if it has a boundary or not
13767+
await A.lazy.lazy.resolve({
13768+
hasErrorBoundary: true,
13769+
});
13770+
expect(t.router.state.location.pathname).toBe("/lazy");
13771+
expect(t.router.state.navigation.state).toBe("idle");
13772+
expect(t.router.state.loaderData).toEqual({});
13773+
expect(t.router.state.errors).toEqual({
13774+
lazy: "STATIC LOADER ERROR",
13775+
});
13776+
13777+
consoleWarn.mockReset();
13778+
});
1374013779
});
1374113780

1374213781
describe("interruptions", () => {

‎packages/router/router.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -3643,10 +3643,19 @@ async function callLoaderOrAction(
36433643
if (match.route.lazy) {
36443644
if (handler) {
36453645
// Run statically defined handler in parallel with lazy()
3646+
let handlerError;
36463647
let values = await Promise.all([
3647-
runHandler(handler),
3648+
// If the handler throws, don't let it immediately bubble out,
3649+
// since we need to let the lazy() execution finish so we know if this
3650+
// route has a boundary that can handle the error
3651+
runHandler(handler).catch((e) => {
3652+
handlerError = e;
3653+
}),
36483654
loadLazyRouteModule(match.route, mapRouteProperties, manifest),
36493655
]);
3656+
if (handlerError) {
3657+
throw handlerError;
3658+
}
36503659
result = values[0];
36513660
} else {
36523661
// Load lazy route module, then run any returned handler

0 commit comments

Comments
 (0)
Please sign in to comment.