@remix-run/router 1.17.0 → 1.17.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remix-run/router",
3
- "version": "1.17.0",
3
+ "version": "1.17.1",
4
4
  "description": "Nested/Data-driven/Framework-agnostic Routing",
5
5
  "keywords": [
6
6
  "remix",
package/router.ts CHANGED
@@ -249,7 +249,8 @@ export interface Router {
249
249
  * PRIVATE DO NOT USE
250
250
  *
251
251
  * Patch additional children routes into an existing parent route
252
- * @param routeId The parent route id
252
+ * @param routeId The parent route id or a callback function accepting `patch`
253
+ * to perform batch patching
253
254
  * @param children The additional children routes
254
255
  */
255
256
  patchRoutes(routeId: string | null, children: AgnosticRouteObject[]): void;
@@ -840,6 +841,20 @@ export function createRouter(init: RouterInit): Router {
840
841
  initialErrors = { [route.id]: error };
841
842
  }
842
843
 
844
+ // If the user provided a patchRoutesOnMiss implementation and our initial
845
+ // match is a splat route, clear them out so we run through lazy discovery
846
+ // on hydration in case there's a more accurate lazy route match
847
+ if (initialMatches && patchRoutesOnMissImpl) {
848
+ let fogOfWar = checkFogOfWar(
849
+ initialMatches,
850
+ dataRoutes,
851
+ init.history.location.pathname
852
+ );
853
+ if (fogOfWar.active) {
854
+ initialMatches = null;
855
+ }
856
+ }
857
+
843
858
  let initialized: boolean;
844
859
  if (!initialMatches) {
845
860
  // We need to run patchRoutesOnMiss in initialize()
@@ -1222,6 +1237,7 @@ export function createRouter(init: RouterInit): Router {
1222
1237
  isMutationMethod(state.navigation.formMethod) &&
1223
1238
  location.state?._isRedirect !== true);
1224
1239
 
1240
+ // Commit any in-flight routes at the end of the HMR revalidation "navigation"
1225
1241
  if (inFlightDataRoutes) {
1226
1242
  dataRoutes = inFlightDataRoutes;
1227
1243
  inFlightDataRoutes = undefined;
@@ -3160,7 +3176,10 @@ export function createRouter(init: RouterInit): Router {
3160
3176
  return { active: true, matches: fogMatches || [] };
3161
3177
  } else {
3162
3178
  let leafRoute = matches[matches.length - 1].route;
3163
- if (leafRoute.path === "*") {
3179
+ if (
3180
+ leafRoute.path &&
3181
+ (leafRoute.path === "*" || leafRoute.path.endsWith("/*"))
3182
+ ) {
3164
3183
  // If we matched a splat, it might only be because we haven't yet fetched
3165
3184
  // the children that would match with a higher score, so let's fetch
3166
3185
  // around and find out
@@ -3204,12 +3223,14 @@ export function createRouter(init: RouterInit): Router {
3204
3223
  ? partialMatches[partialMatches.length - 1].route
3205
3224
  : null;
3206
3225
  while (true) {
3226
+ let isNonHMR = inFlightDataRoutes == null;
3227
+ let routesToUse = inFlightDataRoutes || dataRoutes;
3207
3228
  try {
3208
3229
  await loadLazyRouteChildren(
3209
3230
  patchRoutesOnMissImpl!,
3210
3231
  pathname,
3211
3232
  partialMatches,
3212
- dataRoutes || inFlightDataRoutes,
3233
+ routesToUse,
3213
3234
  manifest,
3214
3235
  mapRouteProperties,
3215
3236
  pendingPatchRoutes,
@@ -3217,13 +3238,22 @@ export function createRouter(init: RouterInit): Router {
3217
3238
  );
3218
3239
  } catch (e) {
3219
3240
  return { type: "error", error: e, partialMatches };
3241
+ } finally {
3242
+ // If we are not in the middle of an HMR revalidation and we changed the
3243
+ // routes, provide a new identity so when we `updateState` at the end of
3244
+ // this navigation/fetch `router.routes` will be a new identity and
3245
+ // trigger a re-run of memoized `router.routes` dependencies.
3246
+ // HMR will already update the identity and reflow when it lands
3247
+ // `inFlightDataRoutes` in `completeNavigation`
3248
+ if (isNonHMR) {
3249
+ dataRoutes = [...dataRoutes];
3250
+ }
3220
3251
  }
3221
3252
 
3222
3253
  if (signal.aborted) {
3223
3254
  return { type: "aborted" };
3224
3255
  }
3225
3256
 
3226
- let routesToUse = inFlightDataRoutes || dataRoutes;
3227
3257
  let newMatches = matchRoutes(routesToUse, pathname, basename);
3228
3258
  let matchedSplat = false;
3229
3259
  if (newMatches) {
@@ -3284,6 +3314,31 @@ export function createRouter(init: RouterInit): Router {
3284
3314
  );
3285
3315
  }
3286
3316
 
3317
+ function patchRoutes(
3318
+ routeId: string | null,
3319
+ children: AgnosticRouteObject[]
3320
+ ): void {
3321
+ let isNonHMR = inFlightDataRoutes == null;
3322
+ let routesToUse = inFlightDataRoutes || dataRoutes;
3323
+ patchRoutesImpl(
3324
+ routeId,
3325
+ children,
3326
+ routesToUse,
3327
+ manifest,
3328
+ mapRouteProperties
3329
+ );
3330
+
3331
+ // If we are not in the middle of an HMR revalidation and we changed the
3332
+ // routes, provide a new identity and trigger a reflow via `updateState`
3333
+ // to re-run memoized `router.routes` dependencies.
3334
+ // HMR will already update the identity and reflow when it lands
3335
+ // `inFlightDataRoutes` in `completeNavigation`
3336
+ if (isNonHMR) {
3337
+ dataRoutes = [...dataRoutes];
3338
+ updateState({});
3339
+ }
3340
+ }
3341
+
3287
3342
  router = {
3288
3343
  get basename() {
3289
3344
  return basename;
@@ -3315,15 +3370,7 @@ export function createRouter(init: RouterInit): Router {
3315
3370
  dispose,
3316
3371
  getBlocker,
3317
3372
  deleteBlocker,
3318
- patchRoutes(routeId, children) {
3319
- return patchRoutes(
3320
- routeId,
3321
- children,
3322
- dataRoutes || inFlightDataRoutes,
3323
- manifest,
3324
- mapRouteProperties
3325
- );
3326
- },
3373
+ patchRoutes,
3327
3374
  _internalFetchControllers: fetchControllers,
3328
3375
  _internalActiveDeferreds: activeDeferreds,
3329
3376
  // TODO: Remove setRoutes, it's temporary to avoid dealing with
@@ -4488,7 +4535,7 @@ function shouldRevalidateLoader(
4488
4535
  }
4489
4536
 
4490
4537
  /**
4491
- * Idempotent utility to execute route.children() method to lazily load route
4538
+ * Idempotent utility to execute patchRoutesOnMiss() to lazily load route
4492
4539
  * definitions and update the routes/routeManifest
4493
4540
  */
4494
4541
  async function loadLazyRouteChildren(
@@ -4510,7 +4557,7 @@ async function loadLazyRouteChildren(
4510
4557
  matches,
4511
4558
  patch: (routeId, children) => {
4512
4559
  if (!signal.aborted) {
4513
- patchRoutes(
4560
+ patchRoutesImpl(
4514
4561
  routeId,
4515
4562
  children,
4516
4563
  routes,
@@ -4531,10 +4578,10 @@ async function loadLazyRouteChildren(
4531
4578
  }
4532
4579
  }
4533
4580
 
4534
- function patchRoutes(
4581
+ function patchRoutesImpl(
4535
4582
  routeId: string | null,
4536
4583
  children: AgnosticRouteObject[],
4537
- routes: AgnosticDataRouteObject[],
4584
+ routesToUse: AgnosticDataRouteObject[],
4538
4585
  manifest: RouteManifest,
4539
4586
  mapRouteProperties: MapRoutePropertiesFunction
4540
4587
  ) {
@@ -4559,10 +4606,10 @@ function patchRoutes(
4559
4606
  let dataChildren = convertRoutesToDataRoutes(
4560
4607
  children,
4561
4608
  mapRouteProperties,
4562
- ["patch", String(routes.length || "0")],
4609
+ ["patch", String(routesToUse.length || "0")],
4563
4610
  manifest
4564
4611
  );
4565
- routes.push(...dataChildren);
4612
+ routesToUse.push(...dataChildren);
4566
4613
  }
4567
4614
  }
4568
4615
 
package/utils.ts CHANGED
@@ -1221,7 +1221,7 @@ export function getResolveToMatches<
1221
1221
  // https://github.com/remix-run/react-router/issues/11052#issuecomment-1836589329
1222
1222
  if (v7_relativeSplatPath) {
1223
1223
  return pathMatches.map((match, idx) =>
1224
- idx === matches.length - 1 ? match.pathname : match.pathnameBase
1224
+ idx === pathMatches.length - 1 ? match.pathname : match.pathnameBase
1225
1225
  );
1226
1226
  }
1227
1227