react-router-dom-v5-compat 6.17.0 → 6.18.0-pre.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/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # `react-router-dom-v5-compat`
2
2
 
3
+ ## 6.18.0-pre.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies:
8
+ - `react-router@6.18.0-pre.1`
9
+ - `react-router-dom@6.18.0-pre.1`
10
+
11
+ ## 6.18.0-pre.0
12
+
13
+ ### Patch Changes
14
+
15
+ - Updated dependencies:
16
+ - `react-router-dom@6.18.0-pre.0`
17
+ - `react-router@6.18.0-pre.0`
18
+
3
19
  ## 6.17.0
4
20
 
5
21
  ### Patch Changes
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * React Router DOM v5 Compat v6.17.0
2
+ * React Router DOM v5 Compat v6.18.0-pre.1
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -11,7 +11,7 @@
11
11
  import * as React from 'react';
12
12
  import { UNSAFE_mapRouteProperties, UNSAFE_DataRouterContext, UNSAFE_DataRouterStateContext, Router, UNSAFE_useRoutesImpl, UNSAFE_NavigationContext, useHref, useResolvedPath, useLocation, useNavigate, createPath, UNSAFE_useRouteId, UNSAFE_RouteContext, useMatches, useNavigation, unstable_useBlocker, Routes, Route } from 'react-router';
13
13
  export { AbortedDeferredError, Await, MemoryRouter, Navigate, NavigationType, Outlet, Route, Router, Routes, UNSAFE_DataRouterContext, UNSAFE_DataRouterStateContext, UNSAFE_LocationContext, UNSAFE_NavigationContext, UNSAFE_RouteContext, UNSAFE_useRouteId, createMemoryRouter, createPath, createRoutesFromChildren, createRoutesFromElements, defer, generatePath, isRouteErrorResponse, json, matchPath, matchRoutes, parsePath, redirect, redirectDocument, renderMatches, resolvePath, unstable_useBlocker, useActionData, useAsyncError, useAsyncValue, useHref, useInRouterContext, useLoaderData, useLocation, useMatch, useMatches, useNavigate, useNavigation, useNavigationType, useOutlet, useOutletContext, useParams, useResolvedPath, useRevalidator, useRouteError, useRouteLoaderData, useRoutes } from 'react-router';
14
- import { stripBasename, UNSAFE_warning, createRouter, createBrowserHistory, createHashHistory, UNSAFE_ErrorResponseImpl, UNSAFE_invariant, joinPaths, matchPath } from '@remix-run/router';
14
+ import { stripBasename, UNSAFE_warning, createRouter, createBrowserHistory, createHashHistory, UNSAFE_ErrorResponseImpl, UNSAFE_invariant, joinPaths, IDLE_FETCHER, matchPath } from '@remix-run/router';
15
15
  import { parsePath, Action, createPath as createPath$1 } from 'history';
16
16
  import { Route as Route$1, useHistory } from 'react-router-dom';
17
17
 
@@ -210,7 +210,7 @@ function getFormSubmissionInfo(target, basename) {
210
210
 
211
211
  const _excluded = ["onClick", "relative", "reloadDocument", "replace", "state", "target", "to", "preventScrollReset", "unstable_viewTransition"],
212
212
  _excluded2 = ["aria-current", "caseSensitive", "className", "end", "style", "to", "unstable_viewTransition", "children"],
213
- _excluded3 = ["reloadDocument", "replace", "state", "method", "action", "onSubmit", "submit", "relative", "preventScrollReset", "unstable_viewTransition"];
213
+ _excluded3 = ["fetcherKey", "navigate", "reloadDocument", "replace", "state", "method", "action", "onSubmit", "relative", "preventScrollReset", "unstable_viewTransition"];
214
214
  function createBrowserRouter(routes, opts) {
215
215
  return createRouter({
216
216
  basename: opts == null ? void 0 : opts.basename,
@@ -296,6 +296,10 @@ const ViewTransitionContext = /*#__PURE__*/React.createContext({
296
296
  if (process.env.NODE_ENV !== "production") {
297
297
  ViewTransitionContext.displayName = "ViewTransition";
298
298
  }
299
+ const FetchersContext = /*#__PURE__*/React.createContext(new Map());
300
+ if (process.env.NODE_ENV !== "production") {
301
+ FetchersContext.displayName = "Fetchers";
302
+ }
299
303
  //#endregion
300
304
  ////////////////////////////////////////////////////////////////////////////////
301
305
  //#region Components
@@ -366,6 +370,7 @@ function RouterProvider(_ref) {
366
370
  let [renderDfd, setRenderDfd] = React.useState();
367
371
  let [transition, setTransition] = React.useState();
368
372
  let [interruption, setInterruption] = React.useState();
373
+ let fetcherData = React.useRef(new Map());
369
374
  let {
370
375
  v7_startTransition
371
376
  } = future || {};
@@ -378,8 +383,15 @@ function RouterProvider(_ref) {
378
383
  }, [v7_startTransition]);
379
384
  let setState = React.useCallback((newState, _ref2) => {
380
385
  let {
386
+ deletedFetchers,
381
387
  unstable_viewTransitionOpts: viewTransitionOpts
382
388
  } = _ref2;
389
+ deletedFetchers.forEach(key => fetcherData.current.delete(key));
390
+ newState.fetchers.forEach((fetcher, key) => {
391
+ if (fetcher.data !== undefined) {
392
+ fetcherData.current.set(key, fetcher.data);
393
+ }
394
+ });
383
395
  if (!viewTransitionOpts || router.window == null || typeof router.window.document.startViewTransition !== "function") {
384
396
  // Mid-navigation state update, or startViewTransition isn't available
385
397
  optInStartTransition(() => setStateImpl(newState));
@@ -402,7 +414,7 @@ function RouterProvider(_ref) {
402
414
  nextLocation: viewTransitionOpts.nextLocation
403
415
  });
404
416
  }
405
- }, [optInStartTransition, transition, renderDfd, router.window]);
417
+ }, [router.window, transition, renderDfd, fetcherData, optInStartTransition]);
406
418
  // Need to use a layout effect here so we are subscribed early enough to
407
419
  // pick up on any render-driven redirects/navigations (useEffect/<Navigate>)
408
420
  React.useLayoutEffect(() => router.subscribe(setState), [router, setState]);
@@ -488,6 +500,8 @@ function RouterProvider(_ref) {
488
500
  value: dataRouterContext
489
501
  }, /*#__PURE__*/React.createElement(UNSAFE_DataRouterStateContext.Provider, {
490
502
  value: state
503
+ }, /*#__PURE__*/React.createElement(FetchersContext.Provider, {
504
+ value: fetcherData.current
491
505
  }, /*#__PURE__*/React.createElement(ViewTransitionContext.Provider, {
492
506
  value: vtContext
493
507
  }, /*#__PURE__*/React.createElement(Router, {
@@ -498,7 +512,7 @@ function RouterProvider(_ref) {
498
512
  }, state.initialized ? /*#__PURE__*/React.createElement(DataRoutes, {
499
513
  routes: router.routes,
500
514
  state: state
501
- }) : fallbackElement)))), null);
515
+ }) : fallbackElement))))), null);
502
516
  }
503
517
  function DataRoutes(_ref3) {
504
518
  let {
@@ -767,34 +781,26 @@ if (process.env.NODE_ENV !== "production") {
767
781
  * requests, allowing components to add nicer UX to the page as the form is
768
782
  * submitted and returns with data.
769
783
  */
770
- const Form = /*#__PURE__*/React.forwardRef((props, ref) => {
771
- let submit = useSubmit();
772
- return /*#__PURE__*/React.createElement(FormImpl, _extends({}, props, {
773
- submit: submit,
774
- ref: ref
775
- }));
776
- });
777
- if (process.env.NODE_ENV !== "production") {
778
- Form.displayName = "Form";
779
- }
780
- const FormImpl = /*#__PURE__*/React.forwardRef((_ref9, forwardedRef) => {
784
+ const Form = /*#__PURE__*/React.forwardRef((_ref9, forwardedRef) => {
781
785
  let {
786
+ fetcherKey,
787
+ navigate,
782
788
  reloadDocument,
783
789
  replace,
784
790
  state,
785
791
  method = defaultMethod,
786
792
  action,
787
793
  onSubmit,
788
- submit,
789
794
  relative,
790
795
  preventScrollReset,
791
796
  unstable_viewTransition
792
797
  } = _ref9,
793
798
  props = _objectWithoutPropertiesLoose(_ref9, _excluded3);
794
- let formMethod = method.toLowerCase() === "get" ? "get" : "post";
799
+ let submit = useSubmit();
795
800
  let formAction = useFormAction(action, {
796
801
  relative
797
802
  });
803
+ let formMethod = method.toLowerCase() === "get" ? "get" : "post";
798
804
  let submitHandler = event => {
799
805
  onSubmit && onSubmit(event);
800
806
  if (event.defaultPrevented) return;
@@ -802,7 +808,9 @@ const FormImpl = /*#__PURE__*/React.forwardRef((_ref9, forwardedRef) => {
802
808
  let submitter = event.nativeEvent.submitter;
803
809
  let submitMethod = (submitter == null ? void 0 : submitter.getAttribute("formmethod")) || method;
804
810
  submit(submitter || event.currentTarget, {
811
+ fetcherKey,
805
812
  method: submitMethod,
813
+ navigate,
806
814
  replace,
807
815
  state,
808
816
  relative,
@@ -818,7 +826,7 @@ const FormImpl = /*#__PURE__*/React.forwardRef((_ref9, forwardedRef) => {
818
826
  }, props));
819
827
  });
820
828
  if (process.env.NODE_ENV !== "production") {
821
- FormImpl.displayName = "FormImpl";
829
+ Form.displayName = "Form";
822
830
  }
823
831
  /**
824
832
  * This component will emulate the browser's scroll restoration on location
@@ -852,9 +860,11 @@ var DataRouterHook;
852
860
  })(DataRouterHook || (DataRouterHook = {}));
853
861
  var DataRouterStateHook;
854
862
  (function (DataRouterStateHook) {
863
+ DataRouterStateHook["UseFetcher"] = "useFetcher";
855
864
  DataRouterStateHook["UseFetchers"] = "useFetchers";
856
865
  DataRouterStateHook["UseScrollRestoration"] = "useScrollRestoration";
857
866
  })(DataRouterStateHook || (DataRouterStateHook = {}));
867
+ // Internal hooks
858
868
  function getDataRouterConsoleError(hookName) {
859
869
  return hookName + " must be used within a data router. See https://reactrouter.com/routers/picking-a-router.";
860
870
  }
@@ -868,6 +878,7 @@ function useDataRouterState(hookName) {
868
878
  !state ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, getDataRouterConsoleError(hookName)) : UNSAFE_invariant(false) : void 0;
869
879
  return state;
870
880
  }
881
+ // External hooks
871
882
  /**
872
883
  * Handles the click behavior for router `<Link>` components. This is useful if
873
884
  * you need to create custom `<Link>` components with the same click behavior we
@@ -930,6 +941,8 @@ function validateClientSideSubmission() {
930
941
  throw new Error("You are calling submit during the server render. " + "Try calling submit within a `useEffect` or callback instead.");
931
942
  }
932
943
  }
944
+ let fetcherId = 0;
945
+ let getUniqueFetcherId = () => "__" + String(++fetcherId) + "__";
933
946
  /**
934
947
  * Returns a function that may be used to programmatically submit a form (or
935
948
  * some arbitrary data) to the server.
@@ -954,50 +967,29 @@ function useSubmit() {
954
967
  formData,
955
968
  body
956
969
  } = getFormSubmissionInfo(target, basename);
957
- router.navigate(options.action || action, {
958
- preventScrollReset: options.preventScrollReset,
959
- formData,
960
- body,
961
- formMethod: options.method || method,
962
- formEncType: options.encType || encType,
963
- replace: options.replace,
964
- state: options.state,
965
- fromRouteId: currentRouteId,
966
- unstable_viewTransition: options.unstable_viewTransition
967
- });
968
- }, [router, basename, currentRouteId]);
969
- }
970
- /**
971
- * Returns the implementation for fetcher.submit
972
- */
973
- function useSubmitFetcher(fetcherKey, fetcherRouteId) {
974
- let {
975
- router
976
- } = useDataRouterContext(DataRouterHook.UseSubmitFetcher);
977
- let {
978
- basename
979
- } = React.useContext(UNSAFE_NavigationContext);
980
- return React.useCallback(function (target, options) {
981
- if (options === void 0) {
982
- options = {};
970
+ if (options.navigate === false) {
971
+ let key = options.fetcherKey || getUniqueFetcherId();
972
+ router.fetch(key, currentRouteId, options.action || action, {
973
+ preventScrollReset: options.preventScrollReset,
974
+ formData,
975
+ body,
976
+ formMethod: options.method || method,
977
+ formEncType: options.encType || encType
978
+ });
979
+ } else {
980
+ router.navigate(options.action || action, {
981
+ preventScrollReset: options.preventScrollReset,
982
+ formData,
983
+ body,
984
+ formMethod: options.method || method,
985
+ formEncType: options.encType || encType,
986
+ replace: options.replace,
987
+ state: options.state,
988
+ fromRouteId: currentRouteId,
989
+ unstable_viewTransition: options.unstable_viewTransition
990
+ });
983
991
  }
984
- validateClientSideSubmission();
985
- let {
986
- action,
987
- method,
988
- encType,
989
- formData,
990
- body
991
- } = getFormSubmissionInfo(target, basename);
992
- !(fetcherRouteId != null) ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, "No routeId available for useFetcher()") : UNSAFE_invariant(false) : void 0;
993
- router.fetch(fetcherKey, fetcherRouteId, options.action || action, {
994
- preventScrollReset: options.preventScrollReset,
995
- formData,
996
- body,
997
- formMethod: options.method || method,
998
- formEncType: options.encType || encType
999
- });
1000
- }, [router, basename, fetcherKey, fetcherRouteId]);
992
+ }, [router, basename, currentRouteId]);
1001
993
  }
1002
994
  // v7: Eventually we should deprecate this entirely in favor of using the
1003
995
  // router method directly?
@@ -1047,63 +1039,76 @@ function useFormAction(action, _temp2) {
1047
1039
  }
1048
1040
  return createPath(path);
1049
1041
  }
1050
- function createFetcherForm(fetcherKey, routeId) {
1051
- let FetcherForm = /*#__PURE__*/React.forwardRef((props, ref) => {
1052
- let submit = useSubmitFetcher(fetcherKey, routeId);
1053
- return /*#__PURE__*/React.createElement(FormImpl, _extends({}, props, {
1054
- ref: ref,
1055
- submit: submit
1056
- }));
1057
- });
1058
- if (process.env.NODE_ENV !== "production") {
1059
- FetcherForm.displayName = "fetcher.Form";
1060
- }
1061
- return FetcherForm;
1062
- }
1063
- let fetcherId = 0;
1064
1042
  // TODO: (v7) Change the useFetcher generic default from `any` to `unknown`
1065
1043
  /**
1066
1044
  * Interacts with route loaders and actions without causing a navigation. Great
1067
1045
  * for any interaction that stays on the same page.
1068
1046
  */
1069
- function useFetcher() {
1047
+ function useFetcher(_temp3) {
1070
1048
  var _route$matches;
1049
+ let {
1050
+ key
1051
+ } = _temp3 === void 0 ? {} : _temp3;
1071
1052
  let {
1072
1053
  router
1073
1054
  } = useDataRouterContext(DataRouterHook.UseFetcher);
1055
+ let state = useDataRouterState(DataRouterStateHook.UseFetcher);
1056
+ let fetcherData = React.useContext(FetchersContext);
1074
1057
  let route = React.useContext(UNSAFE_RouteContext);
1075
- !route ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, "useFetcher must be used inside a RouteContext") : UNSAFE_invariant(false) : void 0;
1076
1058
  let routeId = (_route$matches = route.matches[route.matches.length - 1]) == null ? void 0 : _route$matches.route.id;
1059
+ !fetcherData ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, "useFetcher must be used inside a FetchersContext") : UNSAFE_invariant(false) : void 0;
1060
+ !route ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, "useFetcher must be used inside a RouteContext") : UNSAFE_invariant(false) : void 0;
1077
1061
  !(routeId != null) ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, "useFetcher can only be used on routes that contain a unique \"id\"") : UNSAFE_invariant(false) : void 0;
1078
- let [fetcherKey] = React.useState(() => String(++fetcherId));
1079
- let [Form] = React.useState(() => {
1080
- !routeId ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, "No routeId available for fetcher.Form()") : UNSAFE_invariant(false) : void 0;
1081
- return createFetcherForm(fetcherKey, routeId);
1082
- });
1083
- let [load] = React.useState(() => href => {
1084
- !router ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, "No router available for fetcher.load()") : UNSAFE_invariant(false) : void 0;
1085
- !routeId ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, "No routeId available for fetcher.load()") : UNSAFE_invariant(false) : void 0;
1086
- router.fetch(fetcherKey, routeId, href);
1087
- });
1088
- let submit = useSubmitFetcher(fetcherKey, routeId);
1089
- let fetcher = router.getFetcher(fetcherKey);
1090
- let fetcherWithComponents = React.useMemo(() => _extends({
1091
- Form,
1092
- submit,
1093
- load
1094
- }, fetcher), [fetcher, Form, submit, load]);
1062
+ // Fetcher key handling
1063
+ let [fetcherKey, setFetcherKey] = React.useState(key || "");
1064
+ if (!fetcherKey) {
1065
+ setFetcherKey(getUniqueFetcherId());
1066
+ }
1067
+ // Registration/cleanup
1095
1068
  React.useEffect(() => {
1096
- // Is this busted when the React team gets real weird and calls effects
1097
- // twice on mount? We really just need to garbage collect here when this
1098
- // fetcher is no longer around.
1069
+ router.getFetcher(fetcherKey);
1099
1070
  return () => {
1100
- if (!router) {
1101
- console.warn("No router available to clean up from useFetcher()");
1102
- return;
1103
- }
1071
+ // Tell the router we've unmounted - if v7_fetcherPersist is enabled this
1072
+ // will not delete immediately but instead queue up a delete after the
1073
+ // fetcher returns to an `idle` state
1104
1074
  router.deleteFetcher(fetcherKey);
1105
1075
  };
1106
1076
  }, [router, fetcherKey]);
1077
+ // Fetcher additions
1078
+ let load = React.useCallback(href => {
1079
+ !routeId ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, "No routeId available for fetcher.load()") : UNSAFE_invariant(false) : void 0;
1080
+ router.fetch(fetcherKey, routeId, href);
1081
+ }, [fetcherKey, routeId, router]);
1082
+ let submitImpl = useSubmit();
1083
+ let submit = React.useCallback((target, opts) => {
1084
+ submitImpl(target, _extends({}, opts, {
1085
+ navigate: false,
1086
+ fetcherKey
1087
+ }));
1088
+ }, [fetcherKey, submitImpl]);
1089
+ let FetcherForm = React.useMemo(() => {
1090
+ let FetcherForm = /*#__PURE__*/React.forwardRef((props, ref) => {
1091
+ return /*#__PURE__*/React.createElement(Form, _extends({}, props, {
1092
+ navigate: false,
1093
+ fetcherKey: fetcherKey,
1094
+ ref: ref
1095
+ }));
1096
+ });
1097
+ if (process.env.NODE_ENV !== "production") {
1098
+ FetcherForm.displayName = "fetcher.Form";
1099
+ }
1100
+ return FetcherForm;
1101
+ }, [fetcherKey]);
1102
+ // Exposed FetcherWithComponents
1103
+ let fetcher = state.fetchers.get(fetcherKey) || IDLE_FETCHER;
1104
+ let data = fetcherData.get(fetcherKey);
1105
+ let fetcherWithComponents = React.useMemo(() => _extends({
1106
+ Form: FetcherForm,
1107
+ submit,
1108
+ load
1109
+ }, fetcher, {
1110
+ data
1111
+ }), [FetcherForm, submit, load, fetcher, data]);
1107
1112
  return fetcherWithComponents;
1108
1113
  }
1109
1114
  /**
@@ -1112,18 +1117,23 @@ function useFetcher() {
1112
1117
  */
1113
1118
  function useFetchers() {
1114
1119
  let state = useDataRouterState(DataRouterStateHook.UseFetchers);
1115
- return [...state.fetchers.values()];
1120
+ return Array.from(state.fetchers.entries()).map(_ref11 => {
1121
+ let [key, fetcher] = _ref11;
1122
+ return _extends({}, fetcher, {
1123
+ key
1124
+ });
1125
+ });
1116
1126
  }
1117
1127
  const SCROLL_RESTORATION_STORAGE_KEY = "react-router-scroll-positions";
1118
1128
  let savedScrollPositions = {};
1119
1129
  /**
1120
1130
  * When rendered inside a RouterProvider, will restore scroll positions on navigations
1121
1131
  */
1122
- function useScrollRestoration(_temp3) {
1132
+ function useScrollRestoration(_temp4) {
1123
1133
  let {
1124
1134
  getKey,
1125
1135
  storageKey
1126
- } = _temp3 === void 0 ? {} : _temp3;
1136
+ } = _temp4 === void 0 ? {} : _temp4;
1127
1137
  let {
1128
1138
  router
1129
1139
  } = useDataRouterContext(DataRouterHook.UseScrollRestoration);
@@ -1261,11 +1271,11 @@ function usePageHide(callback, options) {
1261
1271
  * very incorrectly in some cases) across browsers if user click addition
1262
1272
  * back/forward navigations while the confirm is open. Use at your own risk.
1263
1273
  */
1264
- function usePrompt(_ref11) {
1274
+ function usePrompt(_ref12) {
1265
1275
  let {
1266
1276
  when,
1267
1277
  message
1268
- } = _ref11;
1278
+ } = _ref12;
1269
1279
  let blocker = unstable_useBlocker(when);
1270
1280
  React.useEffect(() => {
1271
1281
  if (blocker.state === "blocked") {