react-router 0.0.0-experimental-c0856287f → 0.0.0-experimental-79e23be50

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/dist/index.d.ts CHANGED
@@ -6,10 +6,6 @@ import type { DataRouteMatch, DataRouteObject, IndexRouteObject, NavigateOptions
6
6
  import { DataRouterContext, DataRouterStateContext, LocationContext, NavigationContext, RouteContext } from "./lib/context";
7
7
  import type { NavigateFunction } from "./lib/hooks";
8
8
  import { useActionData, useAsyncError, useAsyncValue, useBlocker, useHref, useInRouterContext, useLoaderData, useLocation, useMatch, useMatches, useNavigate, useNavigation, useNavigationType, useOutlet, useOutletContext, useParams, useResolvedPath, useRevalidator, useRouteError, useRouteId, useRouteLoaderData, useRoutes, useRoutesImpl } from "./lib/hooks";
9
- declare global {
10
- const __DEV__: boolean;
11
- }
12
- export {};
13
9
  type Hash = string;
14
10
  type Pathname = string;
15
11
  type Search = string;
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * React Router v0.0.0-experimental-c0856287f
2
+ * React Router v0.0.0-experimental-79e23be50
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1603,6 +1603,7 @@ function createRouter(init) {
1603
1603
  // Flag to ignore the next history update, so we can revert the URL change on
1604
1604
  // a POP navigation that was blocked by the user without touching router state
1605
1605
  let ignoreNextHistoryUpdate = false;
1606
+ let pendingRevalidationDfd = null;
1606
1607
  // Initialize the router, all side effects should be kicked off from here.
1607
1608
  // Implemented as a Fluent API for ease of:
1608
1609
  // let router = createRouter(init).initialize();
@@ -1739,7 +1740,7 @@ function createRouter(init) {
1739
1740
  // - Navigation will always be set to IDLE_NAVIGATION
1740
1741
  // - Can pass any other state in newState
1741
1742
  function completeNavigation(location, newState, _temp) {
1742
- var _location$state, _location$state2;
1743
+ var _location$state, _location$state2, _pendingRevalidationD;
1743
1744
  let {
1744
1745
  flushSync
1745
1746
  } = _temp === void 0 ? {} : _temp;
@@ -1839,6 +1840,8 @@ function createRouter(init) {
1839
1840
  pendingViewTransitionEnabled = false;
1840
1841
  isUninterruptedRevalidation = false;
1841
1842
  isRevalidationRequired = false;
1843
+ (_pendingRevalidationD = pendingRevalidationDfd) == null ? void 0 : _pendingRevalidationD.resolve();
1844
+ pendingRevalidationDfd = null;
1842
1845
  cancelledDeferredRoutes = [];
1843
1846
  cancelledFetcherLoads = [];
1844
1847
  }
@@ -1906,7 +1909,7 @@ function createRouter(init) {
1906
1909
  });
1907
1910
  return;
1908
1911
  }
1909
- return await startNavigation(historyAction, nextLocation, {
1912
+ await startNavigation(historyAction, nextLocation, {
1910
1913
  submission,
1911
1914
  // Send through the formData serialization error if we have one so we can
1912
1915
  // render at the right error boundary after we match routes
@@ -1921,14 +1924,29 @@ function createRouter(init) {
1921
1924
  // is interrupted by a navigation, allow this to "succeed" by calling all
1922
1925
  // loaders during the next loader round
1923
1926
  function revalidate() {
1927
+ // We can't just return the promise from `startNavigation` because that
1928
+ // navigation may be interrupted and our revalidation wouldn't be finished
1929
+ // until the _next_ navigation completes. Instead we just track via a
1930
+ // deferred and resolve it the next time we run through `completeNavigation`
1931
+ // This is different than navigations which will settle if interrupted
1932
+ // because the navigation to a specific location is no longer relevant.
1933
+ // Revalidations are location-independent and will settle whenever we land
1934
+ // on our final location
1935
+ if (!pendingRevalidationDfd) {
1936
+ pendingRevalidationDfd = createDeferred();
1937
+ }
1924
1938
  interruptActiveLoads();
1925
1939
  updateState({
1926
1940
  revalidation: "loading"
1927
1941
  });
1942
+ // Capture this here for the edge-case that we have a fully synchronous
1943
+ // startNavigation which would resolve and null out pendingRevalidationDfd
1944
+ // before we return from this function
1945
+ let promise = pendingRevalidationDfd.promise;
1928
1946
  // If we're currently submitting an action, we don't need to start a new
1929
1947
  // navigation, we'll just let the follow up loader execution call all loaders
1930
1948
  if (state.navigation.state === "submitting") {
1931
- return;
1949
+ return promise;
1932
1950
  }
1933
1951
  // If we're currently in an idle state, start a new navigation for the current
1934
1952
  // action/location and mark it as uninterrupted, which will skip the history
@@ -1937,7 +1955,7 @@ function createRouter(init) {
1937
1955
  startNavigation(state.historyAction, state.location, {
1938
1956
  startUninterruptedRevalidation: true
1939
1957
  });
1940
- return;
1958
+ return promise;
1941
1959
  }
1942
1960
  // Otherwise, if we're currently in a loading state, just start a new
1943
1961
  // navigation to the navigation.location but do not trigger an uninterrupted
@@ -1945,6 +1963,7 @@ function createRouter(init) {
1945
1963
  startNavigation(pendingAction || state.historyAction, state.navigation.location, {
1946
1964
  overrideNavigation: state.navigation
1947
1965
  });
1966
+ return promise;
1948
1967
  }
1949
1968
  // Start a navigation to the given action/location. Can optionally provide a
1950
1969
  // overrideNavigation which will override the normalLoad in the case of a redirect
@@ -2287,7 +2306,7 @@ function createRouter(init) {
2287
2306
  } : {});
2288
2307
  }
2289
2308
  // Trigger a fetcher load/submit for the given fetcher key
2290
- function fetch(key, routeId, href, opts) {
2309
+ async function fetch(key, routeId, href, opts) {
2291
2310
  if (isServer) {
2292
2311
  throw new Error("router.fetch() was called during the server render, but it shouldn't be. " + "You are likely calling a useFetcher() method in the body of your component. " + "Try moving it to a useEffect or a callback.");
2293
2312
  }
@@ -2318,7 +2337,7 @@ function createRouter(init) {
2318
2337
  let match = getTargetMatch(matches, path);
2319
2338
  pendingPreventScrollReset = (opts && opts.preventScrollReset) === true;
2320
2339
  if (submission && isMutationMethod(submission.formMethod)) {
2321
- handleFetcherAction(key, routeId, path, match, matches, flushSync, submission);
2340
+ await handleFetcherAction(key, routeId, path, match, matches, flushSync, submission);
2322
2341
  return;
2323
2342
  }
2324
2343
  // Store off the match so we can call it's shouldRevalidate on subsequent
@@ -2327,7 +2346,7 @@ function createRouter(init) {
2327
2346
  routeId,
2328
2347
  path
2329
2348
  });
2330
- handleFetcherLoader(key, routeId, path, match, matches, flushSync, submission);
2349
+ await handleFetcherLoader(key, routeId, path, match, matches, flushSync, submission);
2331
2350
  }
2332
2351
  // Call the action for the matched fetcher.submit(), and then handle redirects,
2333
2352
  // errors, and revalidation
@@ -4593,40 +4612,51 @@ function persistAppliedTransitions(_window, transitions) {
4593
4612
  }
4594
4613
  }
4595
4614
  }
4615
+ function createDeferred() {
4616
+ let resolve;
4617
+ let reject;
4618
+ let promise = new Promise((res, rej) => {
4619
+ resolve = async val => {
4620
+ res(val);
4621
+ try {
4622
+ await promise;
4623
+ } catch (e) {}
4624
+ };
4625
+ reject = async error => {
4626
+ rej(error);
4627
+ try {
4628
+ await promise;
4629
+ } catch (e) {}
4630
+ };
4631
+ });
4632
+ return {
4633
+ promise,
4634
+ //@ts-ignore
4635
+ resolve,
4636
+ //@ts-ignore
4637
+ reject
4638
+ };
4639
+ }
4596
4640
  //#endregion
4597
4641
 
4598
4642
  const DataRouterContext = /*#__PURE__*/React.createContext(null);
4599
- if (process.env.NODE_ENV !== "production") {
4600
- DataRouterContext.displayName = "DataRouter";
4601
- }
4643
+ DataRouterContext.displayName = "DataRouter";
4602
4644
  const DataRouterStateContext = /*#__PURE__*/React.createContext(null);
4603
- if (process.env.NODE_ENV !== "production") {
4604
- DataRouterStateContext.displayName = "DataRouterState";
4605
- }
4645
+ DataRouterStateContext.displayName = "DataRouterState";
4606
4646
  const AwaitContext = /*#__PURE__*/React.createContext(null);
4607
- if (process.env.NODE_ENV !== "production") {
4608
- AwaitContext.displayName = "Await";
4609
- }
4647
+ AwaitContext.displayName = "Await";
4610
4648
  const NavigationContext = /*#__PURE__*/React.createContext(null);
4611
- if (process.env.NODE_ENV !== "production") {
4612
- NavigationContext.displayName = "Navigation";
4613
- }
4649
+ NavigationContext.displayName = "Navigation";
4614
4650
  const LocationContext = /*#__PURE__*/React.createContext(null);
4615
- if (process.env.NODE_ENV !== "production") {
4616
- LocationContext.displayName = "Location";
4617
- }
4651
+ LocationContext.displayName = "Location";
4618
4652
  const RouteContext = /*#__PURE__*/React.createContext({
4619
4653
  outlet: null,
4620
4654
  matches: [],
4621
4655
  isDataRoute: false
4622
4656
  });
4623
- if (process.env.NODE_ENV !== "production") {
4624
- RouteContext.displayName = "Route";
4625
- }
4657
+ RouteContext.displayName = "Route";
4626
4658
  const RouteErrorContext = /*#__PURE__*/React.createContext(null);
4627
- if (process.env.NODE_ENV !== "production") {
4628
- RouteErrorContext.displayName = "RouteError";
4629
- }
4659
+ RouteErrorContext.displayName = "RouteError";
4630
4660
 
4631
4661
  /**
4632
4662
  * Returns the full href for the given "to" value. This is useful for building
@@ -4872,7 +4902,7 @@ function useRoutesImpl(routes, locationArg, dataRouterState, future) {
4872
4902
  let parentPathname = routeMatch ? routeMatch.pathname : "/";
4873
4903
  let parentPathnameBase = routeMatch ? routeMatch.pathnameBase : "/";
4874
4904
  let parentRoute = routeMatch && routeMatch.route;
4875
- if (process.env.NODE_ENV !== "production") {
4905
+ {
4876
4906
  // You won't get a warning about 2 different <Routes> under a <Route>
4877
4907
  // without a trailing *, but this is a best-effort warning anyway since we
4878
4908
  // cannot even give the warning unless they land at the parent route.
@@ -4930,7 +4960,7 @@ function useRoutesImpl(routes, locationArg, dataRouterState, future) {
4930
4960
  let matches = matchRoutes(routes, {
4931
4961
  pathname: remainingPathname
4932
4962
  });
4933
- if (process.env.NODE_ENV !== "production") {
4963
+ {
4934
4964
  process.env.NODE_ENV !== "production" ? warning(parentRoute || matches != null, "No routes matched location \"" + location.pathname + location.search + location.hash + "\" ") : void 0;
4935
4965
  process.env.NODE_ENV !== "production" ? warning(matches == null || matches[matches.length - 1].route.element !== undefined || matches[matches.length - 1].route.Component !== undefined || matches[matches.length - 1].route.lazy !== undefined, "Matched leaf route at location \"" + location.pathname + location.search + location.hash + "\" " + "does not have an element or Component. This means it will render an <Outlet /> with a " + "null value by default resulting in an \"empty\" page.") : void 0;
4936
4966
  }
@@ -4976,7 +5006,7 @@ function DefaultErrorComponent() {
4976
5006
  backgroundColor: lightgrey
4977
5007
  };
4978
5008
  let devInfo = null;
4979
- if (process.env.NODE_ENV !== "production") {
5009
+ {
4980
5010
  console.error("Error handled by React Router default ErrorBoundary:", error);
4981
5011
  devInfo = /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("p", null, "\uD83D\uDCBF Hey developer \uD83D\uDC4B"), /*#__PURE__*/React.createElement("p", null, "You can provide a way better UX than this when your app throws errors by providing your own ", /*#__PURE__*/React.createElement("code", {
4982
5012
  style: codeStyles
@@ -5255,9 +5285,11 @@ function useRevalidator() {
5255
5285
  let dataRouterContext = useDataRouterContext$2(DataRouterHook$1.UseRevalidator);
5256
5286
  let state = useDataRouterState$1(DataRouterStateHook$1.UseRevalidator);
5257
5287
  return React.useMemo(() => ({
5258
- revalidate: dataRouterContext.router.revalidate,
5288
+ async revalidate() {
5289
+ await dataRouterContext.router.revalidate();
5290
+ },
5259
5291
  state: state.revalidation
5260
- }), [dataRouterContext.router.revalidate, state.revalidation]);
5292
+ }), [dataRouterContext.router, state.revalidation]);
5261
5293
  }
5262
5294
  /**
5263
5295
  * Returns the active route matches, useful for accessing loaderData for
@@ -5401,7 +5433,7 @@ function useNavigateStable() {
5401
5433
  useIsomorphicLayoutEffect(() => {
5402
5434
  activeRef.current = true;
5403
5435
  });
5404
- let navigate = React.useCallback(function (to, options) {
5436
+ let navigate = React.useCallback(async function (to, options) {
5405
5437
  if (options === void 0) {
5406
5438
  options = {};
5407
5439
  }
@@ -5412,7 +5444,7 @@ function useNavigateStable() {
5412
5444
  if (typeof to === "number") {
5413
5445
  router.navigate(to);
5414
5446
  } else {
5415
- router.navigate(to, _extends({
5447
+ await router.navigate(to, _extends({
5416
5448
  fromRouteId: id
5417
5449
  }, options));
5418
5450
  }
@@ -5434,7 +5466,7 @@ function mapRouteProperties(route) {
5434
5466
  hasErrorBoundary: route.hasErrorBoundary || route.ErrorBoundary != null || route.errorElement != null
5435
5467
  };
5436
5468
  if (route.Component) {
5437
- if (process.env.NODE_ENV !== "production") {
5469
+ {
5438
5470
  if (route.element) {
5439
5471
  process.env.NODE_ENV !== "production" ? warning(false, "You should not include both `Component` and `element` on your route - " + "`Component` will be used.") : void 0;
5440
5472
  }
@@ -5445,7 +5477,7 @@ function mapRouteProperties(route) {
5445
5477
  });
5446
5478
  }
5447
5479
  if (route.HydrateFallback) {
5448
- if (process.env.NODE_ENV !== "production") {
5480
+ {
5449
5481
  if (route.hydrateFallbackElement) {
5450
5482
  process.env.NODE_ENV !== "production" ? warning(false, "You should not include both `HydrateFallback` and `hydrateFallbackElement` on your route - " + "`HydrateFallback` will be used.") : void 0;
5451
5483
  }
@@ -5456,7 +5488,7 @@ function mapRouteProperties(route) {
5456
5488
  });
5457
5489
  }
5458
5490
  if (route.ErrorBoundary) {
5459
- if (process.env.NODE_ENV !== "production") {
5491
+ {
5460
5492
  if (route.errorElement) {
5461
5493
  process.env.NODE_ENV !== "production" ? warning(false, "You should not include both `ErrorBoundary` and `errorElement` on your route - " + "`ErrorBoundary` will be used.") : void 0;
5462
5494
  }
@@ -5667,11 +5699,13 @@ function Navigate(_ref4) {
5667
5699
  // StrictMode they navigate to the same place
5668
5700
  let path = resolveTo(to, getResolveToMatches(matches, future.v7_relativeSplatPath), locationPathname, relative === "path");
5669
5701
  let jsonPath = JSON.stringify(path);
5670
- React.useEffect(() => navigate(JSON.parse(jsonPath), {
5671
- replace,
5672
- state,
5673
- relative
5674
- }), [navigate, jsonPath, relative, replace, state]);
5702
+ React.useEffect(() => {
5703
+ navigate(JSON.parse(jsonPath), {
5704
+ replace,
5705
+ state,
5706
+ relative
5707
+ });
5708
+ }, [navigate, jsonPath, relative, replace, state]);
5675
5709
  return null;
5676
5710
  }
5677
5711
  /**
@@ -7698,13 +7732,9 @@ function deserializeErrors$1(errors) {
7698
7732
  const ViewTransitionContext = /*#__PURE__*/React.createContext({
7699
7733
  isTransitioning: false
7700
7734
  });
7701
- if (process.env.NODE_ENV !== "production") {
7702
- ViewTransitionContext.displayName = "ViewTransition";
7703
- }
7735
+ ViewTransitionContext.displayName = "ViewTransition";
7704
7736
  const FetchersContext = /*#__PURE__*/React.createContext(new Map());
7705
- if (process.env.NODE_ENV !== "production") {
7706
- FetchersContext.displayName = "Fetchers";
7707
- }
7737
+ FetchersContext.displayName = "Fetchers";
7708
7738
  //#endregion
7709
7739
  ////////////////////////////////////////////////////////////////////////////////
7710
7740
  //#region Components
@@ -8103,9 +8133,7 @@ function HistoryRouter(_ref6) {
8103
8133
  future: future
8104
8134
  });
8105
8135
  }
8106
- if (process.env.NODE_ENV !== "production") {
8107
- HistoryRouter.displayName = "unstable_HistoryRouter";
8108
- }
8136
+ HistoryRouter.displayName = "unstable_HistoryRouter";
8109
8137
  const ABSOLUTE_URL_REGEX$1 = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
8110
8138
  /**
8111
8139
  * The public API for rendering a history-aware `<a>`.
@@ -8184,9 +8212,7 @@ const Link = /*#__PURE__*/React.forwardRef(function LinkWithRef(_ref7, forwarded
8184
8212
  page: href
8185
8213
  }))) : link;
8186
8214
  });
8187
- if (process.env.NODE_ENV !== "production") {
8188
- Link.displayName = "Link";
8189
- }
8215
+ Link.displayName = "Link";
8190
8216
  /**
8191
8217
  * A `<Link>` wrapper that knows if it's "active" or not.
8192
8218
  */
@@ -8261,9 +8287,7 @@ const NavLink = /*#__PURE__*/React.forwardRef(function NavLinkWithRef(_ref8, ref
8261
8287
  unstable_viewTransition: unstable_viewTransition
8262
8288
  }), typeof children === "function" ? children(renderProps) : children);
8263
8289
  });
8264
- if (process.env.NODE_ENV !== "production") {
8265
- NavLink.displayName = "NavLink";
8266
- }
8290
+ NavLink.displayName = "NavLink";
8267
8291
  /**
8268
8292
  * A `@remix-run/router`-aware `<form>`. It behaves like a normal form except
8269
8293
  * that the interaction with the server is with `fetch` instead of new document
@@ -8314,9 +8338,7 @@ const Form = /*#__PURE__*/React.forwardRef((_ref9, forwardedRef) => {
8314
8338
  onSubmit: reloadDocument ? onSubmit : submitHandler
8315
8339
  }, props));
8316
8340
  });
8317
- if (process.env.NODE_ENV !== "production") {
8318
- Form.displayName = "Form";
8319
- }
8341
+ Form.displayName = "Form";
8320
8342
  /**
8321
8343
  * This component will emulate the browser's scroll restoration on location
8322
8344
  * changes.
@@ -8381,9 +8403,7 @@ function ScrollRestoration(_ref10) {
8381
8403
  }
8382
8404
  }));
8383
8405
  }
8384
- if (process.env.NODE_ENV !== "production") {
8385
- ScrollRestoration.displayName = "ScrollRestoration";
8386
- }
8406
+ ScrollRestoration.displayName = "ScrollRestoration";
8387
8407
  //#endregion
8388
8408
  ////////////////////////////////////////////////////////////////////////////////
8389
8409
  //#region Hooks
@@ -8493,7 +8513,7 @@ function useSubmit() {
8493
8513
  basename
8494
8514
  } = React.useContext(NavigationContext);
8495
8515
  let currentRouteId = useRouteId();
8496
- return React.useCallback(function (target, options) {
8516
+ return React.useCallback(async function (target, options) {
8497
8517
  if (options === void 0) {
8498
8518
  options = {};
8499
8519
  }
@@ -8507,7 +8527,7 @@ function useSubmit() {
8507
8527
  } = getFormSubmissionInfo(target, basename);
8508
8528
  if (options.navigate === false) {
8509
8529
  let key = options.fetcherKey || getUniqueFetcherId();
8510
- router.fetch(key, currentRouteId, options.action || action, {
8530
+ await router.fetch(key, currentRouteId, options.action || action, {
8511
8531
  preventScrollReset: options.preventScrollReset,
8512
8532
  formData,
8513
8533
  body,
@@ -8516,7 +8536,7 @@ function useSubmit() {
8516
8536
  unstable_flushSync: options.unstable_flushSync
8517
8537
  });
8518
8538
  } else {
8519
- router.navigate(options.action || action, {
8539
+ await router.navigate(options.action || action, {
8520
8540
  preventScrollReset: options.preventScrollReset,
8521
8541
  formData,
8522
8542
  body,
@@ -8619,13 +8639,13 @@ function useFetcher(_temp3) {
8619
8639
  };
8620
8640
  }, [router, fetcherKey]);
8621
8641
  // Fetcher additions
8622
- let load = React.useCallback((href, opts) => {
8642
+ let load = React.useCallback(async (href, opts) => {
8623
8643
  !routeId ? process.env.NODE_ENV !== "production" ? invariant$1(false, "No routeId available for fetcher.load()") : invariant$1(false) : void 0;
8624
- router.fetch(fetcherKey, routeId, href, opts);
8644
+ await router.fetch(fetcherKey, routeId, href, opts);
8625
8645
  }, [fetcherKey, routeId, router]);
8626
8646
  let submitImpl = useSubmit();
8627
- let submit = React.useCallback((target, opts) => {
8628
- submitImpl(target, _extends({}, opts, {
8647
+ let submit = React.useCallback(async (target, opts) => {
8648
+ await submitImpl(target, _extends({}, opts, {
8629
8649
  navigate: false,
8630
8650
  fetcherKey
8631
8651
  }));
@@ -8638,9 +8658,7 @@ function useFetcher(_temp3) {
8638
8658
  ref: ref
8639
8659
  }));
8640
8660
  });
8641
- if (process.env.NODE_ENV !== "production") {
8642
- FetcherForm.displayName = "fetcher.Form";
8643
- }
8661
+ FetcherForm.displayName = "fetcher.Form";
8644
8662
  return FetcherForm;
8645
8663
  }, [fetcherKey]);
8646
8664
  // Exposed FetcherWithComponents
@@ -9989,7 +10007,11 @@ function HydratedRouter() {
9989
10007
  }, /*#__PURE__*/React.createElement(RemixErrorBoundary, {
9990
10008
  location: location
9991
10009
  }, /*#__PURE__*/React.createElement(RouterProvider, {
9992
- router: router
10010
+ router: router,
10011
+ fallbackElement: null,
10012
+ future: {
10013
+ v7_startTransition: true
10014
+ }
9993
10015
  }))), ssrInfo.context.future.unstable_singleFetch ? /*#__PURE__*/React.createElement(React.Fragment, null) : null)
9994
10016
  );
9995
10017
  }