react-router 7.15.0 → 7.15.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.
Files changed (60) hide show
  1. package/CHANGELOG.md +50 -10
  2. package/dist/development/{browser-CRsXgNrY.d.mts → browser-3AnU12UI.d.mts} +1 -1
  3. package/dist/development/{browser-wDl1FZEL.d.ts → browser-BOdXz9dK.d.ts} +1 -1
  4. package/dist/development/{chunk-5KNZJZUH.mjs → chunk-4N6VE7H7.mjs} +230 -113
  5. package/dist/{production/chunk-7YXKJMLN.js → development/chunk-4YRVXM2U.js} +7 -7
  6. package/dist/development/{chunk-Z5YQYACE.js → chunk-66UKHEGQ.js} +106 -103
  7. package/dist/development/{chunk-AM3XM4LS.js → chunk-D6LUOGOQ.js} +251 -137
  8. package/dist/development/{chunk-RMD3H4O3.mjs → chunk-RJYABSBD.mjs} +22 -21
  9. package/dist/{production/context-BQs41HrG.d.mts → development/context-ByvtofY2.d.mts} +7 -1
  10. package/dist/development/dom-export.d.mts +2 -2
  11. package/dist/development/dom-export.d.ts +2 -2
  12. package/dist/development/dom-export.js +48 -50
  13. package/dist/development/dom-export.mjs +23 -25
  14. package/dist/{production/index-react-server-client-CSv-KZBk.d.ts → development/index-react-server-client-BS5F89FR.d.ts} +10 -2
  15. package/dist/{production/index-react-server-client-Ck_yZ1qL.d.mts → development/index-react-server-client-DY04-103.d.mts} +10 -2
  16. package/dist/development/index-react-server-client.d.mts +2 -2
  17. package/dist/development/index-react-server-client.d.ts +2 -2
  18. package/dist/development/index-react-server-client.js +4 -4
  19. package/dist/development/index-react-server-client.mjs +2 -2
  20. package/dist/development/index-react-server.d.mts +6 -0
  21. package/dist/development/index-react-server.d.ts +6 -0
  22. package/dist/development/index-react-server.js +4 -4
  23. package/dist/development/index-react-server.mjs +4 -4
  24. package/dist/development/index.d.mts +91 -9
  25. package/dist/development/index.d.ts +91 -9
  26. package/dist/development/index.js +103 -100
  27. package/dist/development/index.mjs +5 -3
  28. package/dist/{production/instrumentation-DlJ2QV7d.d.ts → development/instrumentation-cRWWLfsU.d.ts} +7 -1
  29. package/dist/development/lib/types/internal.js +1 -1
  30. package/dist/development/lib/types/internal.mjs +1 -1
  31. package/dist/production/{browser-CRsXgNrY.d.mts → browser-3AnU12UI.d.mts} +1 -1
  32. package/dist/production/{browser-wDl1FZEL.d.ts → browser-BOdXz9dK.d.ts} +1 -1
  33. package/dist/production/{chunk-23ZOHYE5.mjs → chunk-6S4627ZB.mjs} +22 -21
  34. package/dist/production/{chunk-LCJTIOKZ.js → chunk-HUBUW7R3.js} +251 -137
  35. package/dist/production/{chunk-GM3PW4GX.mjs → chunk-JAKZPQZC.mjs} +230 -113
  36. package/dist/production/{chunk-YBQJ3ABE.js → chunk-PNZCCTKT.js} +106 -103
  37. package/dist/{development/chunk-2D5H3HU3.js → production/chunk-Y6IFXO7V.js} +7 -7
  38. package/dist/{development/context-BQs41HrG.d.mts → production/context-ByvtofY2.d.mts} +7 -1
  39. package/dist/production/dom-export.d.mts +2 -2
  40. package/dist/production/dom-export.d.ts +2 -2
  41. package/dist/production/dom-export.js +48 -50
  42. package/dist/production/dom-export.mjs +23 -25
  43. package/dist/{development/index-react-server-client-CSv-KZBk.d.ts → production/index-react-server-client-BS5F89FR.d.ts} +10 -2
  44. package/dist/{development/index-react-server-client-Ck_yZ1qL.d.mts → production/index-react-server-client-DY04-103.d.mts} +10 -2
  45. package/dist/production/index-react-server-client.d.mts +2 -2
  46. package/dist/production/index-react-server-client.d.ts +2 -2
  47. package/dist/production/index-react-server-client.js +4 -4
  48. package/dist/production/index-react-server-client.mjs +2 -2
  49. package/dist/production/index-react-server.d.mts +6 -0
  50. package/dist/production/index-react-server.d.ts +6 -0
  51. package/dist/production/index-react-server.js +4 -4
  52. package/dist/production/index-react-server.mjs +4 -4
  53. package/dist/production/index.d.mts +91 -9
  54. package/dist/production/index.d.ts +91 -9
  55. package/dist/production/index.js +103 -100
  56. package/dist/production/index.mjs +5 -3
  57. package/dist/{development/instrumentation-DlJ2QV7d.d.ts → production/instrumentation-cRWWLfsU.d.ts} +7 -1
  58. package/dist/production/lib/types/internal.js +1 -1
  59. package/dist/production/lib/types/internal.mjs +1 -1
  60. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v7.15.0
2
+ * react-router v7.15.1
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1323,6 +1323,8 @@ var redirectPreserveMethodStatusCodes = /* @__PURE__ */ new Set([307, 308]);
1323
1323
  var IDLE_NAVIGATION = {
1324
1324
  state: "idle",
1325
1325
  location: void 0,
1326
+ matches: void 0,
1327
+ historyAction: void 0,
1326
1328
  formMethod: void 0,
1327
1329
  formAction: void 0,
1328
1330
  formEncType: void 0,
@@ -1441,6 +1443,7 @@ function createRouter(init) {
1441
1443
  };
1442
1444
  let unlistenHistory = null;
1443
1445
  let subscribers = /* @__PURE__ */ new Set();
1446
+ let bufferedInitialStateUpdate = null;
1444
1447
  let savedScrollPositions2 = null;
1445
1448
  let getScrollRestorationKey2 = null;
1446
1449
  let getScrollPosition = null;
@@ -1622,11 +1625,21 @@ function createRouter(init) {
1622
1625
  }
1623
1626
  subscribers.clear();
1624
1627
  pendingNavigationController && pendingNavigationController.abort();
1625
- state.fetchers.forEach((_, key) => deleteFetcher(key));
1628
+ state.fetchers.forEach((_, key) => deleteFetcher(state.fetchers, key));
1626
1629
  state.blockers.forEach((_, key) => deleteBlocker(key));
1627
1630
  }
1628
1631
  function subscribe(fn) {
1629
1632
  subscribers.add(fn);
1633
+ if (bufferedInitialStateUpdate) {
1634
+ let { newErrors } = bufferedInitialStateUpdate;
1635
+ bufferedInitialStateUpdate = null;
1636
+ fn(state, {
1637
+ deletedFetchers: [],
1638
+ newErrors,
1639
+ viewTransitionOpts: void 0,
1640
+ flushSync: false
1641
+ });
1642
+ }
1630
1643
  return () => subscribers.delete(fn);
1631
1644
  }
1632
1645
  function updateState(newState, opts = {}) {
@@ -1663,6 +1676,9 @@ function createRouter(init) {
1663
1676
  unmountedFetchers.push(key);
1664
1677
  }
1665
1678
  });
1679
+ if (subscribers.size === 0) {
1680
+ bufferedInitialStateUpdate = { newErrors: newState.errors ?? null };
1681
+ }
1666
1682
  [...subscribers].forEach(
1667
1683
  (subscriber) => subscriber(state, {
1668
1684
  deletedFetchers: unmountedFetchers,
@@ -1671,7 +1687,7 @@ function createRouter(init) {
1671
1687
  flushSync: opts.flushSync === true
1672
1688
  })
1673
1689
  );
1674
- unmountedFetchers.forEach((key) => deleteFetcher(key));
1690
+ unmountedFetchers.forEach((key) => deleteFetcher(state.fetchers, key));
1675
1691
  mountedFetchers.forEach((key) => state.fetchers.delete(key));
1676
1692
  }
1677
1693
  function completeNavigation(location, newState, { flushSync } = {}) {
@@ -1900,7 +1916,6 @@ function createRouter(init) {
1900
1916
  pendingPreventScrollReset = (opts && opts.preventScrollReset) === true;
1901
1917
  pendingViewTransitionEnabled = (opts && opts.enableViewTransition) === true;
1902
1918
  let routesToUse = dataRoutes.activeRoutes;
1903
- let loadingNavigation = opts && opts.overrideNavigation;
1904
1919
  let matches = opts?.initialHydration && state.matches && state.matches.length > 0 && !initialMatchesIsFOW ? (
1905
1920
  // `matchRoutes()` has already been called if we're in here via `router.initialize()`
1906
1921
  state.matches
@@ -1937,6 +1952,11 @@ function createRouter(init) {
1937
1952
  );
1938
1953
  return;
1939
1954
  }
1955
+ let loadingNavigation = opts && opts.overrideNavigation ? {
1956
+ ...opts.overrideNavigation,
1957
+ matches,
1958
+ historyAction
1959
+ } : void 0;
1940
1960
  pendingNavigationController = new AbortController();
1941
1961
  let request = createClientSideRequest(
1942
1962
  init.history,
@@ -1957,6 +1977,7 @@ function createRouter(init) {
1957
1977
  location,
1958
1978
  opts.submission,
1959
1979
  matches,
1980
+ historyAction,
1960
1981
  scopedContext,
1961
1982
  fogOfWar.active,
1962
1983
  opts && opts.initialHydration === true,
@@ -1981,7 +2002,12 @@ function createRouter(init) {
1981
2002
  }
1982
2003
  matches = actionResult.matches || matches;
1983
2004
  pendingActionResult = actionResult.pendingActionResult;
1984
- loadingNavigation = getLoadingNavigation(location, opts.submission);
2005
+ loadingNavigation = getLoadingNavigation(
2006
+ location,
2007
+ matches,
2008
+ historyAction,
2009
+ opts.submission
2010
+ );
1985
2011
  flushSync = false;
1986
2012
  fogOfWar.active = false;
1987
2013
  request = createClientSideRequest(
@@ -1994,11 +2020,13 @@ function createRouter(init) {
1994
2020
  shortCircuited,
1995
2021
  matches: updatedMatches,
1996
2022
  loaderData,
1997
- errors
2023
+ errors,
2024
+ workingFetchers
1998
2025
  } = await handleLoaders(
1999
2026
  request,
2000
2027
  location,
2001
2028
  matches,
2029
+ historyAction,
2002
2030
  scopedContext,
2003
2031
  fogOfWar.active,
2004
2032
  loadingNavigation,
@@ -2018,12 +2046,18 @@ function createRouter(init) {
2018
2046
  matches: updatedMatches || matches,
2019
2047
  ...getActionDataForCommit(pendingActionResult),
2020
2048
  loaderData,
2021
- errors
2049
+ errors,
2050
+ ...workingFetchers ? { fetchers: workingFetchers } : {}
2022
2051
  });
2023
2052
  }
2024
- async function handleAction(request, location, submission, matches, scopedContext, isFogOfWar, initialHydration, opts = {}) {
2053
+ async function handleAction(request, location, submission, matches, historyAction, scopedContext, isFogOfWar, initialHydration, opts = {}) {
2025
2054
  interruptActiveLoads();
2026
- let navigation = getSubmittingNavigation(location, submission);
2055
+ let navigation = getSubmittingNavigation(
2056
+ location,
2057
+ matches,
2058
+ historyAction,
2059
+ submission
2060
+ );
2027
2061
  updateState({ navigation }, { flushSync: opts.flushSync === true });
2028
2062
  if (isFogOfWar) {
2029
2063
  let discoverResult = await discoverRoutes(
@@ -2158,8 +2192,8 @@ function createRouter(init) {
2158
2192
  pendingActionResult: [actionMatch.route.id, result]
2159
2193
  };
2160
2194
  }
2161
- async function handleLoaders(request, location, matches, scopedContext, isFogOfWar, overrideNavigation, submission, fetcherSubmission, replace2, initialHydration, flushSync, pendingActionResult, callSiteDefaultShouldRevalidate) {
2162
- let loadingNavigation = overrideNavigation || getLoadingNavigation(location, submission);
2195
+ async function handleLoaders(request, location, matches, historyAction, scopedContext, isFogOfWar, overrideNavigation, submission, fetcherSubmission, replace2, initialHydration, flushSync, pendingActionResult, callSiteDefaultShouldRevalidate) {
2196
+ let loadingNavigation = overrideNavigation || getLoadingNavigation(location, matches, historyAction, submission);
2163
2197
  let activeSubmission = submission || fetcherSubmission || getSubmissionFromNavigation(loadingNavigation);
2164
2198
  let shouldUpdateNavigationState = !isUninterruptedRevalidation && !initialHydration;
2165
2199
  if (isFogOfWar) {
@@ -2247,7 +2281,8 @@ function createRouter(init) {
2247
2281
  if (!init.dataStrategy && !dsMatches.some((m) => m.shouldLoad) && !dsMatches.some(
2248
2282
  (m) => m.route.middleware && m.route.middleware.length > 0
2249
2283
  ) && revalidatingFetchers.length === 0) {
2250
- let updatedFetchers2 = markFetchRedirectsDone();
2284
+ let workingFetchers2 = new Map(state.fetchers);
2285
+ let didUpdateFetcherRedirects2 = markFetchRedirectsDone(workingFetchers2);
2251
2286
  completeNavigation(
2252
2287
  location,
2253
2288
  {
@@ -2256,7 +2291,7 @@ function createRouter(init) {
2256
2291
  // Commit pending error if we're short circuiting
2257
2292
  errors: pendingActionResult && isErrorResult(pendingActionResult[1]) ? { [pendingActionResult[0]]: pendingActionResult[1].error } : null,
2258
2293
  ...getActionDataForCommit(pendingActionResult),
2259
- ...updatedFetchers2 ? { fetchers: new Map(state.fetchers) } : {}
2294
+ ...didUpdateFetcherRedirects2 ? { fetchers: workingFetchers2 } : {}
2260
2295
  },
2261
2296
  { flushSync }
2262
2297
  );
@@ -2321,25 +2356,30 @@ function createRouter(init) {
2321
2356
  });
2322
2357
  return { shortCircuited: true };
2323
2358
  }
2359
+ let workingFetchers = new Map(state.fetchers);
2324
2360
  let { loaderData, errors } = processLoaderData(
2325
2361
  state,
2326
2362
  matches,
2327
2363
  loaderResults,
2328
2364
  pendingActionResult,
2329
2365
  revalidatingFetchers,
2330
- fetcherResults
2366
+ fetcherResults,
2367
+ workingFetchers
2331
2368
  );
2332
2369
  if (initialHydration && state.errors) {
2333
2370
  errors = { ...state.errors, ...errors };
2334
2371
  }
2335
- let updatedFetchers = markFetchRedirectsDone();
2336
- let didAbortFetchLoads = abortStaleFetchLoads(pendingNavigationLoadId);
2337
- let shouldUpdateFetchers = updatedFetchers || didAbortFetchLoads || revalidatingFetchers.length > 0;
2372
+ let didUpdateFetcherRedirects = markFetchRedirectsDone(workingFetchers);
2373
+ let didAbortFetchLoads = abortStaleFetchLoads(
2374
+ pendingNavigationLoadId,
2375
+ workingFetchers
2376
+ );
2377
+ let shouldUpdateFetchers = didUpdateFetcherRedirects || didAbortFetchLoads || revalidatingFetchers.length > 0;
2338
2378
  return {
2339
2379
  matches,
2340
2380
  loaderData,
2341
2381
  errors,
2342
- ...shouldUpdateFetchers ? { fetchers: new Map(state.fetchers) } : {}
2382
+ ...shouldUpdateFetchers ? { workingFetchers } : {}
2343
2383
  };
2344
2384
  }
2345
2385
  function getUpdatedActionData(pendingActionResult) {
@@ -2356,15 +2396,16 @@ function createRouter(init) {
2356
2396
  }
2357
2397
  }
2358
2398
  function getUpdatedRevalidatingFetchers(revalidatingFetchers) {
2399
+ let workingFetchers = new Map(state.fetchers);
2359
2400
  revalidatingFetchers.forEach((rf) => {
2360
- let fetcher = state.fetchers.get(rf.key);
2401
+ let fetcher = workingFetchers.get(rf.key);
2361
2402
  let revalidatingFetcher = getLoadingFetcher(
2362
2403
  void 0,
2363
2404
  fetcher ? fetcher.data : void 0
2364
2405
  );
2365
- state.fetchers.set(rf.key, revalidatingFetcher);
2406
+ workingFetchers.set(rf.key, revalidatingFetcher);
2366
2407
  });
2367
- return new Map(state.fetchers);
2408
+ return workingFetchers;
2368
2409
  }
2369
2410
  async function fetch2(key, routeId, href, opts) {
2370
2411
  abortFetcher(key);
@@ -2561,8 +2602,6 @@ function createRouter(init) {
2561
2602
  invariant(matches, "Didn't find any matches after fetcher action");
2562
2603
  let loadId = ++incrementingLoadId;
2563
2604
  fetchReloadIds.set(key, loadId);
2564
- let loadFetcher = getLoadingFetcher(submission, actionResult.data);
2565
- state.fetchers.set(key, loadFetcher);
2566
2605
  let { dsMatches, revalidatingFetchers } = getMatchesToLoad(
2567
2606
  revalidationRequest,
2568
2607
  scopedContext,
@@ -2587,20 +2626,23 @@ function createRouter(init) {
2587
2626
  [match.route.id, actionResult],
2588
2627
  callSiteDefaultShouldRevalidate
2589
2628
  );
2629
+ let loadFetcher = getLoadingFetcher(submission, actionResult.data);
2630
+ let workingFetchers = new Map(state.fetchers);
2631
+ workingFetchers.set(key, loadFetcher);
2590
2632
  revalidatingFetchers.filter((rf) => rf.key !== key).forEach((rf) => {
2591
2633
  let staleKey = rf.key;
2592
- let existingFetcher2 = state.fetchers.get(staleKey);
2634
+ let existingFetcher2 = workingFetchers.get(staleKey);
2593
2635
  let revalidatingFetcher = getLoadingFetcher(
2594
2636
  void 0,
2595
2637
  existingFetcher2 ? existingFetcher2.data : void 0
2596
2638
  );
2597
- state.fetchers.set(staleKey, revalidatingFetcher);
2639
+ workingFetchers.set(staleKey, revalidatingFetcher);
2598
2640
  abortFetcher(staleKey);
2599
2641
  if (rf.controller) {
2600
2642
  fetchControllers.set(staleKey, rf.controller);
2601
2643
  }
2602
2644
  });
2603
- updateState({ fetchers: new Map(state.fetchers) });
2645
+ updateState({ fetchers: workingFetchers });
2604
2646
  let abortPendingFetchRevalidations = () => revalidatingFetchers.forEach((rf) => abortFetcher(rf.key));
2605
2647
  abortController.signal.addEventListener(
2606
2648
  "abort",
@@ -2623,12 +2665,16 @@ function createRouter(init) {
2623
2665
  fetchReloadIds.delete(key);
2624
2666
  fetchControllers.delete(key);
2625
2667
  revalidatingFetchers.forEach((r) => fetchControllers.delete(r.key));
2626
- if (state.fetchers.has(key)) {
2627
- let doneFetcher = getDoneFetcher(actionResult.data);
2628
- state.fetchers.set(key, doneFetcher);
2629
- }
2668
+ let fetcherIsMounted = state.fetchers.has(key);
2669
+ let getRedirectStateWithDoneFetcher = (s) => {
2670
+ if (!fetcherIsMounted) return s;
2671
+ let workingFetchers2 = new Map(s.fetchers);
2672
+ workingFetchers2.set(key, getDoneFetcher(actionResult.data));
2673
+ return { ...s, fetchers: workingFetchers2 };
2674
+ };
2630
2675
  let redirect2 = findRedirect(loaderResults);
2631
2676
  if (redirect2) {
2677
+ state = getRedirectStateWithDoneFetcher(state);
2632
2678
  return startRedirectNavigation(
2633
2679
  revalidationRequest,
2634
2680
  redirect2.result,
@@ -2639,6 +2685,7 @@ function createRouter(init) {
2639
2685
  redirect2 = findRedirect(fetcherResults);
2640
2686
  if (redirect2) {
2641
2687
  fetchRedirectIds.add(redirect2.key);
2688
+ state = getRedirectStateWithDoneFetcher(state);
2642
2689
  return startRedirectNavigation(
2643
2690
  revalidationRequest,
2644
2691
  redirect2.result,
@@ -2646,15 +2693,20 @@ function createRouter(init) {
2646
2693
  { preventScrollReset }
2647
2694
  );
2648
2695
  }
2696
+ let finalFetchers = new Map(state.fetchers);
2697
+ if (fetcherIsMounted) {
2698
+ finalFetchers.set(key, getDoneFetcher(actionResult.data));
2699
+ }
2649
2700
  let { loaderData, errors } = processLoaderData(
2650
2701
  state,
2651
2702
  matches,
2652
2703
  loaderResults,
2653
2704
  void 0,
2654
2705
  revalidatingFetchers,
2655
- fetcherResults
2706
+ fetcherResults,
2707
+ finalFetchers
2656
2708
  );
2657
- abortStaleFetchLoads(loadId);
2709
+ abortStaleFetchLoads(loadId, finalFetchers);
2658
2710
  if (state.navigation.state === "loading" && loadId > pendingNavigationLoadId) {
2659
2711
  invariant(pendingAction, "Expected pending action");
2660
2712
  pendingNavigationController && pendingNavigationController.abort();
@@ -2662,7 +2714,7 @@ function createRouter(init) {
2662
2714
  matches,
2663
2715
  loaderData,
2664
2716
  errors,
2665
- fetchers: new Map(state.fetchers)
2717
+ fetchers: finalFetchers
2666
2718
  });
2667
2719
  } else {
2668
2720
  updateState({
@@ -2673,7 +2725,7 @@ function createRouter(init) {
2673
2725
  matches,
2674
2726
  errors
2675
2727
  ),
2676
- fetchers: new Map(state.fetchers)
2728
+ fetchers: finalFetchers
2677
2729
  });
2678
2730
  isRevalidationRequired = false;
2679
2731
  }
@@ -2838,6 +2890,8 @@ function createRouter(init) {
2838
2890
  } else {
2839
2891
  let overrideNavigation = getLoadingNavigation(
2840
2892
  redirectLocation,
2893
+ [],
2894
+ redirectNavigationType,
2841
2895
  submission
2842
2896
  );
2843
2897
  await startNavigation(redirectNavigationType, redirectLocation, {
@@ -2961,21 +3015,23 @@ function createRouter(init) {
2961
3015
  });
2962
3016
  }
2963
3017
  function updateFetcherState(key, fetcher, opts = {}) {
2964
- state.fetchers.set(key, fetcher);
3018
+ let workingFetchers = new Map(state.fetchers);
3019
+ workingFetchers.set(key, fetcher);
2965
3020
  updateState(
2966
- { fetchers: new Map(state.fetchers) },
3021
+ { fetchers: workingFetchers },
2967
3022
  { flushSync: (opts && opts.flushSync) === true }
2968
3023
  );
2969
3024
  }
2970
3025
  function setFetcherError(key, routeId, error, opts = {}) {
2971
3026
  let boundaryMatch = findNearestBoundary(state.matches, routeId);
2972
- deleteFetcher(key);
3027
+ let workingFetchers = new Map(state.fetchers);
3028
+ deleteFetcher(workingFetchers, key);
2973
3029
  updateState(
2974
3030
  {
2975
3031
  errors: {
2976
3032
  [boundaryMatch.route.id]: error
2977
3033
  },
2978
- fetchers: new Map(state.fetchers)
3034
+ fetchers: workingFetchers
2979
3035
  },
2980
3036
  { flushSync: (opts && opts.flushSync) === true }
2981
3037
  );
@@ -2991,7 +3047,7 @@ function createRouter(init) {
2991
3047
  abortFetcher(key, opts?.reason);
2992
3048
  updateFetcherState(key, getDoneFetcher(null));
2993
3049
  }
2994
- function deleteFetcher(key) {
3050
+ function deleteFetcher(fetchers, key) {
2995
3051
  let fetcher = state.fetchers.get(key);
2996
3052
  if (fetchControllers.has(key) && !(fetcher && fetcher.state === "loading" && fetchReloadIds.has(key))) {
2997
3053
  abortFetcher(key);
@@ -3001,7 +3057,7 @@ function createRouter(init) {
3001
3057
  fetchRedirectIds.delete(key);
3002
3058
  fetchersQueuedForDeletion.delete(key);
3003
3059
  cancelledFetcherLoads.delete(key);
3004
- state.fetchers.delete(key);
3060
+ fetchers.delete(key);
3005
3061
  }
3006
3062
  function queueFetcherForDeletion(key) {
3007
3063
  let count = (activeFetchers.get(key) || 0) - 1;
@@ -3020,33 +3076,34 @@ function createRouter(init) {
3020
3076
  fetchControllers.delete(key);
3021
3077
  }
3022
3078
  }
3023
- function markFetchersDone(keys) {
3079
+ function markFetchersDone(keys, fetchers) {
3024
3080
  for (let key of keys) {
3025
- let fetcher = getFetcher(key);
3081
+ let fetcher = fetchers.get(key);
3082
+ invariant(fetcher, `Expected fetcher: ${key}`);
3026
3083
  let doneFetcher = getDoneFetcher(fetcher.data);
3027
- state.fetchers.set(key, doneFetcher);
3084
+ fetchers.set(key, doneFetcher);
3028
3085
  }
3029
3086
  }
3030
- function markFetchRedirectsDone() {
3087
+ function markFetchRedirectsDone(fetchers) {
3031
3088
  let doneKeys = [];
3032
- let updatedFetchers = false;
3089
+ let didUpdateFetchers = false;
3033
3090
  for (let key of fetchRedirectIds) {
3034
- let fetcher = state.fetchers.get(key);
3091
+ let fetcher = fetchers.get(key);
3035
3092
  invariant(fetcher, `Expected fetcher: ${key}`);
3036
3093
  if (fetcher.state === "loading") {
3037
3094
  fetchRedirectIds.delete(key);
3038
3095
  doneKeys.push(key);
3039
- updatedFetchers = true;
3096
+ didUpdateFetchers = true;
3040
3097
  }
3041
3098
  }
3042
- markFetchersDone(doneKeys);
3043
- return updatedFetchers;
3099
+ markFetchersDone(doneKeys, fetchers);
3100
+ return didUpdateFetchers;
3044
3101
  }
3045
- function abortStaleFetchLoads(landedId) {
3102
+ function abortStaleFetchLoads(landedId, fetchers) {
3046
3103
  let yeetedKeys = [];
3047
3104
  for (let [key, id] of fetchReloadIds) {
3048
3105
  if (id < landedId) {
3049
- let fetcher = state.fetchers.get(key);
3106
+ let fetcher = fetchers.get(key);
3050
3107
  invariant(fetcher, `Expected fetcher: ${key}`);
3051
3108
  if (fetcher.state === "loading") {
3052
3109
  abortFetcher(key);
@@ -3055,7 +3112,7 @@ function createRouter(init) {
3055
3112
  }
3056
3113
  }
3057
3114
  }
3058
- markFetchersDone(yeetedKeys);
3115
+ markFetchersDone(yeetedKeys, fetchers);
3059
3116
  return yeetedKeys.length > 0;
3060
3117
  }
3061
3118
  function getBlocker(key, fn) {
@@ -5283,7 +5340,7 @@ function processRouteLoaderData(matches, results, pendingActionResult, isStaticH
5283
5340
  loaderHeaders
5284
5341
  };
5285
5342
  }
5286
- function processLoaderData(state, matches, results, pendingActionResult, revalidatingFetchers, fetcherResults) {
5343
+ function processLoaderData(state, matches, results, pendingActionResult, revalidatingFetchers, fetcherResults, workingFetchers) {
5287
5344
  let { loaderData, errors } = processRouteLoaderData(
5288
5345
  matches,
5289
5346
  results,
@@ -5304,12 +5361,12 @@ function processLoaderData(state, matches, results, pendingActionResult, revalid
5304
5361
  [boundaryMatch.route.id]: result.error
5305
5362
  };
5306
5363
  }
5307
- state.fetchers.delete(key);
5364
+ workingFetchers.delete(key);
5308
5365
  } else if (isRedirectResult(result)) {
5309
5366
  invariant(false, "Unhandled fetcher revalidation redirect");
5310
5367
  } else {
5311
5368
  let doneFetcher = getDoneFetcher(result.data);
5312
- state.fetchers.set(key, doneFetcher);
5369
+ workingFetchers.set(key, doneFetcher);
5313
5370
  }
5314
5371
  });
5315
5372
  return { loaderData, errors };
@@ -5516,11 +5573,13 @@ function getSubmissionFromNavigation(navigation) {
5516
5573
  };
5517
5574
  }
5518
5575
  }
5519
- function getLoadingNavigation(location, submission) {
5576
+ function getLoadingNavigation(location, matches, historyAction, submission) {
5520
5577
  if (submission) {
5521
5578
  let navigation = {
5522
5579
  state: "loading",
5523
5580
  location,
5581
+ matches,
5582
+ historyAction,
5524
5583
  formMethod: submission.formMethod,
5525
5584
  formAction: submission.formAction,
5526
5585
  formEncType: submission.formEncType,
@@ -5533,6 +5592,8 @@ function getLoadingNavigation(location, submission) {
5533
5592
  let navigation = {
5534
5593
  state: "loading",
5535
5594
  location,
5595
+ matches,
5596
+ historyAction,
5536
5597
  formMethod: void 0,
5537
5598
  formAction: void 0,
5538
5599
  formEncType: void 0,
@@ -5543,10 +5604,12 @@ function getLoadingNavigation(location, submission) {
5543
5604
  return navigation;
5544
5605
  }
5545
5606
  }
5546
- function getSubmittingNavigation(location, submission) {
5607
+ function getSubmittingNavigation(location, matches, historyAction, submission) {
5547
5608
  let navigation = {
5548
5609
  state: "submitting",
5549
5610
  location,
5611
+ matches,
5612
+ historyAction,
5550
5613
  formMethod: submission.formMethod,
5551
5614
  formAction: submission.formAction,
5552
5615
  formEncType: submission.formEncType,
@@ -6279,7 +6342,10 @@ function useRouteId() {
6279
6342
  }
6280
6343
  function useNavigation() {
6281
6344
  let state = useDataRouterState("useNavigation" /* UseNavigation */);
6282
- return state.navigation;
6345
+ return React2.useMemo(() => {
6346
+ let { matches, historyAction, ...rest } = state.navigation;
6347
+ return rest;
6348
+ }, [state.navigation]);
6283
6349
  }
6284
6350
  function useRevalidator() {
6285
6351
  let dataRouterContext = useDataRouterContext("useRevalidator" /* UseRevalidator */);
@@ -6414,6 +6480,65 @@ function useRoute(...args) {
6414
6480
  actionData: state.actionData?.[id]
6415
6481
  };
6416
6482
  }
6483
+ function toRouterStateMatch(match) {
6484
+ return {
6485
+ id: match.route.id,
6486
+ pathname: match.pathname,
6487
+ params: match.params,
6488
+ handle: match.route.handle
6489
+ };
6490
+ }
6491
+ function useRouterState() {
6492
+ let {
6493
+ location,
6494
+ historyAction: type,
6495
+ matches,
6496
+ navigation
6497
+ } = useDataRouterState("unstable_useRouterState" /* UseRouterState */);
6498
+ let active = React2.useMemo(
6499
+ () => ({
6500
+ type,
6501
+ location,
6502
+ searchParams: new URLSearchParams(location.search),
6503
+ params: matches[matches.length - 1]?.params ?? {},
6504
+ matches: matches.map((m) => toRouterStateMatch(m))
6505
+ }),
6506
+ [location, matches, type]
6507
+ );
6508
+ let pending = React2.useMemo(() => {
6509
+ if (navigation.state === "idle") return null;
6510
+ let shared = {
6511
+ type: navigation.historyAction,
6512
+ location: navigation.location,
6513
+ searchParams: new URLSearchParams(navigation.location.search),
6514
+ params: navigation.matches[navigation.matches.length - 1]?.params ?? {},
6515
+ matches: navigation.matches.map((m) => toRouterStateMatch(m))
6516
+ };
6517
+ return navigation.state === "loading" ? {
6518
+ ...shared,
6519
+ state: "loading",
6520
+ formMethod: navigation.formMethod,
6521
+ formAction: navigation.formAction,
6522
+ formEncType: navigation.formEncType,
6523
+ formData: navigation.formData,
6524
+ json: navigation.json,
6525
+ text: navigation.text
6526
+ } : {
6527
+ ...shared,
6528
+ state: "submitting",
6529
+ formMethod: navigation.formMethod,
6530
+ formAction: navigation.formAction,
6531
+ formEncType: navigation.formEncType,
6532
+ formData: navigation.formData,
6533
+ json: navigation.json,
6534
+ text: navigation.text
6535
+ };
6536
+ }, [navigation]);
6537
+ return React2.useMemo(
6538
+ () => ({ active, pending }),
6539
+ [active, pending]
6540
+ );
6541
+ }
6417
6542
 
6418
6543
  // lib/components.tsx
6419
6544
  import * as React3 from "react";
@@ -6644,16 +6769,6 @@ function RouterProvider({
6644
6769
  ]
6645
6770
  );
6646
6771
  React3.useLayoutEffect(() => router.subscribe(setState), [router, setState]);
6647
- let initialized = state.initialized;
6648
- React3.useLayoutEffect(() => {
6649
- if (!initialized && router.state.initialized) {
6650
- setState(router.state, {
6651
- deletedFetchers: [],
6652
- flushSync: false,
6653
- newErrors: null
6654
- });
6655
- }
6656
- }, [initialized, setState, router.state]);
6657
6772
  React3.useEffect(() => {
6658
6773
  if (vtContext.isTransitioning && !vtContext.flushSync) {
6659
6774
  setRenderDfd(new Deferred());
@@ -8971,39 +9086,37 @@ function createClientRoutes(manifest, routeModulesCache, initialState, ssr, isSp
8971
9086
  let initialError = hasInitialError ? initialState?.errors?.[route.id] : void 0;
8972
9087
  let isHydrationRequest = needsRevalidation == null && (routeModule.clientLoader?.hydrate === true || !route.hasLoader);
8973
9088
  dataRoute.loader = async ({ request, params, context, pattern, url }, singleFetch) => {
8974
- try {
8975
- let result = await prefetchStylesAndCallHandler(async () => {
8976
- invariant2(
8977
- routeModule,
8978
- "No `routeModule` available for critical-route loader"
8979
- );
8980
- if (!routeModule.clientLoader) {
8981
- return fetchServerLoader(singleFetch);
8982
- }
8983
- return routeModule.clientLoader({
8984
- request,
8985
- params,
8986
- context,
8987
- pattern,
8988
- url,
8989
- async serverLoader() {
8990
- preventInvalidServerHandlerCall("loader", route);
8991
- if (isHydrationRequest) {
8992
- if (hasInitialData) {
8993
- return initialData;
8994
- }
8995
- if (hasInitialError) {
8996
- throw initialError;
8997
- }
9089
+ let _isHydrationRequest = isHydrationRequest;
9090
+ isHydrationRequest = false;
9091
+ let result = await prefetchStylesAndCallHandler(async () => {
9092
+ invariant2(
9093
+ routeModule,
9094
+ "No `routeModule` available for critical-route loader"
9095
+ );
9096
+ if (!routeModule.clientLoader) {
9097
+ return fetchServerLoader(singleFetch);
9098
+ }
9099
+ return routeModule.clientLoader({
9100
+ request,
9101
+ params,
9102
+ context,
9103
+ pattern,
9104
+ url,
9105
+ async serverLoader() {
9106
+ preventInvalidServerHandlerCall("loader", route);
9107
+ if (_isHydrationRequest) {
9108
+ if (hasInitialData) {
9109
+ return initialData;
9110
+ }
9111
+ if (hasInitialError) {
9112
+ throw initialError;
8998
9113
  }
8999
- return fetchServerLoader(singleFetch);
9000
9114
  }
9001
- });
9115
+ return fetchServerLoader(singleFetch);
9116
+ }
9002
9117
  });
9003
- return result;
9004
- } finally {
9005
- isHydrationRequest = false;
9006
- }
9118
+ });
9119
+ return result;
9007
9120
  };
9008
9121
  dataRoute.loader.hydrate = shouldHydrateRouteLoader(
9009
9122
  route.id,
@@ -9828,7 +9941,7 @@ function Meta() {
9828
9941
  dangerouslySetInnerHTML: { __html: escapeHtml(json) }
9829
9942
  }
9830
9943
  );
9831
- } catch (err) {
9944
+ } catch (e) {
9832
9945
  return null;
9833
9946
  }
9834
9947
  }
@@ -9944,13 +10057,16 @@ import(${JSON.stringify(manifest.entry.module)});`;
9944
10057
  }
9945
10058
  ));
9946
10059
  }, []);
9947
- let preloads = isHydrated || isRSCRouterContext ? [] : dedupe(
9948
- manifest.entry.imports.concat(
9949
- getModuleLinkHrefs(matches, manifest, {
9950
- includeHydrateFallback: true
9951
- })
10060
+ let preloads = isHydrated || isRSCRouterContext ? [] : [
10061
+ // Dedupe through a Set
10062
+ ...new Set(
10063
+ manifest.entry.imports.concat(
10064
+ getModuleLinkHrefs(matches, manifest, {
10065
+ includeHydrateFallback: true
10066
+ })
10067
+ )
9952
10068
  )
9953
- );
10069
+ ];
9954
10070
  let sri = typeof manifest.sri === "object" ? manifest.sri : {};
9955
10071
  warnOnce(
9956
10072
  !isRSCRouterContext,
@@ -10002,9 +10118,6 @@ import(${JSON.stringify(manifest.entry.module)});`;
10002
10118
  }
10003
10119
  )), initialScripts);
10004
10120
  }
10005
- function dedupe(array) {
10006
- return [...new Set(array)];
10007
- }
10008
10121
  function mergeRefs(...refs) {
10009
10122
  return (value) => {
10010
10123
  refs.forEach((ref) => {
@@ -10120,7 +10233,7 @@ var isBrowser2 = typeof window !== "undefined" && typeof window.document !== "un
10120
10233
  try {
10121
10234
  if (isBrowser2) {
10122
10235
  window.__reactRouterVersion = // @ts-expect-error
10123
- "7.15.0";
10236
+ "7.15.1";
10124
10237
  }
10125
10238
  } catch (e) {
10126
10239
  }
@@ -10814,10 +10927,13 @@ function useFetcher({
10814
10927
  }
10815
10928
  function useFetchers() {
10816
10929
  let state = useDataRouterState2("useFetchers" /* UseFetchers */);
10817
- return Array.from(state.fetchers.entries()).map(([key, fetcher]) => ({
10818
- ...fetcher,
10819
- key
10820
- }));
10930
+ return React10.useMemo(
10931
+ () => Array.from(state.fetchers.entries()).map(([key, fetcher]) => ({
10932
+ ...fetcher,
10933
+ key
10934
+ })),
10935
+ [state.fetchers]
10936
+ );
10821
10937
  }
10822
10938
  var SCROLL_RESTORATION_STORAGE_KEY = "react-router-scroll-positions";
10823
10939
  var savedScrollPositions = {};
@@ -11334,6 +11450,7 @@ export {
11334
11450
  useAsyncError,
11335
11451
  useBlocker,
11336
11452
  useRoute,
11453
+ useRouterState,
11337
11454
  warnOnce,
11338
11455
  mapRouteProperties,
11339
11456
  hydrationRouteProperties,