Skip to content

Commit

Permalink
Fix initial matching in fog of war when a splat route matches (#11759)
Browse files Browse the repository at this point in the history
  • Loading branch information
brophdawg11 committed Jul 1, 2024
1 parent eb30a88 commit ff041d1
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 3 deletions.
5 changes: 5 additions & 0 deletions .changeset/rich-bees-invent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@remix-run/router": patch
---

Fix initial matching in fog of war when a splat route matches
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@
},
"filesize": {
"packages/router/dist/router.umd.min.js": {
"none": "56.3 kB"
"none": "56.4 kB"
},
"packages/react-router/dist/react-router.production.min.js": {
"none": "14.9 kB"
Expand Down
63 changes: 62 additions & 1 deletion packages/router/__tests__/lazy-discovery-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,34 @@ describe("Lazy Route Discovery (Fog of War)", () => {
expect(router.state.matches.map((m) => m.route.id)).toEqual(["a", "b"]);
});

it("de-prioritizes splat routes in favor of looking for better async matches (splat/*)", async () => {
router = createRouter({
history: createMemoryHistory(),
routes: [
{
path: "/",
},
{
id: "splat",
path: "/splat/*",
},
],
async unstable_patchRoutesOnMiss({ matches, patch }) {
await tick();
patch(null, [
{
id: "static",
path: "/splat/static",
},
]);
},
});

await router.navigate("/splat/static");
expect(router.state.location.pathname).toBe("/splat/static");
expect(router.state.matches.map((m) => m.route.id)).toEqual(["static"]);
});

it("matches splats when other paths don't pan out", async () => {
router = createRouter({
history: createMemoryHistory(),
Expand Down Expand Up @@ -628,6 +656,39 @@ describe("Lazy Route Discovery (Fog of War)", () => {
]);
});

it("discovers routes during initial hydration when a splat route matches", async () => {
let childrenDfd = createDeferred<AgnosticDataRouteObject[]>();

router = createRouter({
history: createMemoryHistory({ initialEntries: ["/test"] }),
routes: [
{
path: "/",
},
{
path: "*",
},
],
async unstable_patchRoutesOnMiss({ path, patch, matches }) {
let children = await childrenDfd.promise;
patch(null, children);
},
});
router.initialize();
expect(router.state.initialized).toBe(false);

childrenDfd.resolve([
{
id: "test",
path: "/test",
},
]);
await tick();
expect(router.state.initialized).toBe(true);
expect(router.state.location.pathname).toBe("/test");
expect(router.state.matches.map((m) => m.route.id)).toEqual(["test"]);
});

it("discovers new root routes", async () => {
let childrenDfd = createDeferred<AgnosticDataRouteObject[]>();
let childLoaderDfd = createDeferred();
Expand Down Expand Up @@ -737,7 +798,7 @@ describe("Lazy Route Discovery (Fog of War)", () => {
let childLoaderDfd = createDeferred();

router = createRouter({
history: createMemoryHistory(),
history: createMemoryHistory({ initialEntries: ["/other"] }),
routes: [
{
id: "other",
Expand Down
19 changes: 18 additions & 1 deletion packages/router/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -841,6 +841,20 @@ export function createRouter(init: RouterInit): Router {
initialErrors = { [route.id]: error };
}

// If the user provided a patchRoutesOnMiss implementation and our initial
// match is a splat route, clear them out so we run through lazy discovery
// on hydration in case there's a more accurate lazy route match
if (initialMatches && patchRoutesOnMissImpl) {
let fogOfWar = checkFogOfWar(
initialMatches,
dataRoutes,
init.history.location.pathname
);
if (fogOfWar.active) {
initialMatches = null;
}
}

let initialized: boolean;
if (!initialMatches) {
// We need to run patchRoutesOnMiss in initialize()
Expand Down Expand Up @@ -3162,7 +3176,10 @@ export function createRouter(init: RouterInit): Router {
return { active: true, matches: fogMatches || [] };
} else {
let leafRoute = matches[matches.length - 1].route;
if (leafRoute.path === "*") {
if (
leafRoute.path &&
(leafRoute.path === "*" || leafRoute.path.endsWith("/*"))
) {
// If we matched a splat, it might only be because we haven't yet fetched
// the children that would match with a higher score, so let's fetch
// around and find out
Expand Down

0 comments on commit ff041d1

Please sign in to comment.