@remix-run/router 1.11.0-pre.0 → 1.11.0

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.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @remix-run/router v1.11.0-pre.0
2
+ * @remix-run/router v1.11.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1785,6 +1785,9 @@
1785
1785
  // Most recent href/match for fetcher.load calls for fetchers
1786
1786
  let fetchLoadMatches = new Map();
1787
1787
 
1788
+ // Ref-count mounted fetchers so we know when it's ok to clean them up
1789
+ let activeFetchers = new Map();
1790
+
1788
1791
  // Fetchers that have requested a delete when using v7_fetcherPersist,
1789
1792
  // they'll be officially removed after they return to idle
1790
1793
  let deletedFetchers = new Set();
@@ -1901,27 +1904,35 @@
1901
1904
  // Update our state and notify the calling context of the change
1902
1905
  function updateState(newState, viewTransitionOpts) {
1903
1906
  state = _extends({}, state, newState);
1904
- subscribers.forEach(subscriber => subscriber(state, {
1905
- unstable_viewTransitionOpts: viewTransitionOpts
1906
- }));
1907
1907
 
1908
- // Remove idle fetchers from state since we only care about in-flight fetchers.
1908
+ // Prep fetcher cleanup so we can tell the UI which fetcher data entries
1909
+ // can be removed
1910
+ let completedFetchers = [];
1911
+ let deletedFetchersKeys = [];
1909
1912
  if (future.v7_fetcherPersist) {
1910
1913
  state.fetchers.forEach((fetcher, key) => {
1911
1914
  if (fetcher.state === "idle") {
1912
1915
  if (deletedFetchers.has(key)) {
1913
- // If the fetcher has unmounted and called router.deleteFetcher(),
1914
- // we can totally delete the fetcher
1915
- deleteFetcher(key);
1916
+ // Unmounted from the UI and can be totally removed
1917
+ deletedFetchersKeys.push(key);
1916
1918
  } else {
1917
- // Otherwise, it must still be mounted in the UI so we just remove
1918
- // it from state now that we've handed off the data to the React
1919
- // layer. Things such as fetchLoadMatches remain for revalidation.
1920
- state.fetchers.delete(key);
1919
+ // Returned to idle but still mounted in the UI, so semi-remains for
1920
+ // revalidations and such
1921
+ completedFetchers.push(key);
1921
1922
  }
1922
1923
  }
1923
1924
  });
1924
1925
  }
1926
+ subscribers.forEach(subscriber => subscriber(state, {
1927
+ deletedFetchers: deletedFetchersKeys,
1928
+ unstable_viewTransitionOpts: viewTransitionOpts
1929
+ }));
1930
+
1931
+ // Remove idle fetchers from state since we only care about in-flight fetchers.
1932
+ if (future.v7_fetcherPersist) {
1933
+ completedFetchers.forEach(key => state.fetchers.delete(key));
1934
+ deletedFetchersKeys.forEach(key => deleteFetcher(key));
1935
+ }
1925
1936
  }
1926
1937
 
1927
1938
  // Complete a navigation returning the state.navigation back to the IDLE_NAVIGATION
@@ -2474,6 +2485,14 @@
2474
2485
  } : {});
2475
2486
  }
2476
2487
  function getFetcher(key) {
2488
+ if (future.v7_fetcherPersist) {
2489
+ activeFetchers.set(key, (activeFetchers.get(key) || 0) + 1);
2490
+ // If this fetcher was previously marked for deletion, unmark it since we
2491
+ // have a new instance
2492
+ if (deletedFetchers.has(key)) {
2493
+ deletedFetchers.delete(key);
2494
+ }
2495
+ }
2477
2496
  return state.fetchers.get(key) || IDLE_FETCHER;
2478
2497
  }
2479
2498
 
@@ -2547,13 +2566,20 @@
2547
2566
  let originatingLoadId = incrementingLoadId;
2548
2567
  let actionResult = await callLoaderOrAction("action", fetchRequest, match, requestMatches, manifest, mapRouteProperties, basename);
2549
2568
  if (fetchRequest.signal.aborted) {
2550
- // We can delete this so long as we weren't aborted by ou our own fetcher
2569
+ // We can delete this so long as we weren't aborted by our own fetcher
2551
2570
  // re-submit which would have put _new_ controller is in fetchControllers
2552
2571
  if (fetchControllers.get(key) === abortController) {
2553
2572
  fetchControllers.delete(key);
2554
2573
  }
2555
2574
  return;
2556
2575
  }
2576
+ if (deletedFetchers.has(key)) {
2577
+ state.fetchers.set(key, getDoneFetcher(undefined));
2578
+ updateState({
2579
+ fetchers: new Map(state.fetchers)
2580
+ });
2581
+ return;
2582
+ }
2557
2583
  if (isRedirectResult(actionResult)) {
2558
2584
  fetchControllers.delete(key);
2559
2585
  if (pendingNavigationLoadId > originatingLoadId) {
@@ -2723,6 +2749,13 @@
2723
2749
  if (fetchRequest.signal.aborted) {
2724
2750
  return;
2725
2751
  }
2752
+ if (deletedFetchers.has(key)) {
2753
+ state.fetchers.set(key, getDoneFetcher(undefined));
2754
+ updateState({
2755
+ fetchers: new Map(state.fetchers)
2756
+ });
2757
+ return;
2758
+ }
2726
2759
 
2727
2760
  // If the loader threw a redirect Response, start a new REPLACE navigation
2728
2761
  if (isRedirectResult(result)) {
@@ -2744,17 +2777,7 @@
2744
2777
 
2745
2778
  // Process any non-redirect errors thrown
2746
2779
  if (isErrorResult(result)) {
2747
- let boundaryMatch = findNearestBoundary(state.matches, routeId);
2748
- state.fetchers.delete(key);
2749
- // TODO: In remix, this would reset to IDLE_NAVIGATION if it was a catch -
2750
- // do we need to behave any differently with our non-redirect errors?
2751
- // What if it was a non-redirect Response?
2752
- updateState({
2753
- fetchers: new Map(state.fetchers),
2754
- errors: {
2755
- [boundaryMatch.route.id]: result.error
2756
- }
2757
- });
2780
+ setFetcherError(key, routeId, result.error);
2758
2781
  return;
2759
2782
  }
2760
2783
  invariant(!isDeferredResult(result), "Unhandled fetcher deferred data");
@@ -2931,7 +2954,13 @@
2931
2954
  }
2932
2955
  function deleteFetcherAndUpdateState(key) {
2933
2956
  if (future.v7_fetcherPersist) {
2934
- deletedFetchers.add(key);
2957
+ let count = (activeFetchers.get(key) || 0) - 1;
2958
+ if (count <= 0) {
2959
+ activeFetchers.delete(key);
2960
+ deletedFetchers.add(key);
2961
+ } else {
2962
+ activeFetchers.set(key, count);
2963
+ }
2935
2964
  } else {
2936
2965
  deleteFetcher(key);
2937
2966
  }