react-router-dom-v5-compat 6.17.0-pre.2 → 6.18.0-pre.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.
package/CHANGELOG.md CHANGED
@@ -1,28 +1,20 @@
1
1
  # `react-router-dom-v5-compat`
2
2
 
3
- ## 6.17.0-pre.2
3
+ ## 6.18.0-pre.0
4
4
 
5
5
  ### Patch Changes
6
6
 
7
7
  - Updated dependencies:
8
- - `react-router-dom@6.17.0-pre.2`
9
- - `react-router@6.17.0-pre.2`
8
+ - `react-router-dom@6.18.0-pre.0`
9
+ - `react-router@6.18.0-pre.0`
10
10
 
11
- ## 6.17.0-pre.1
11
+ ## 6.17.0
12
12
 
13
13
  ### Patch Changes
14
14
 
15
15
  - Updated dependencies:
16
- - `react-router@6.17.0-pre.1`
17
- - `react-router-dom@6.17.0-pre.1`
18
-
19
- ## 6.17.0-pre.0
20
-
21
- ### Patch Changes
22
-
23
- - Updated dependencies:
24
- - `react-router@6.17.0-pre.0`
25
- - `react-router-dom@6.17.0-pre.0`
16
+ - `react-router-dom@6.17.0`
17
+ - `react-router@6.17.0`
26
18
 
27
19
  ## 6.16.0
28
20
 
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * React Router DOM v5 Compat v6.17.0-pre.2
2
+ * React Router DOM v5 Compat v6.18.0-pre.0
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(null);
300
+ if (process.env.NODE_ENV !== "production") {
301
+ FetchersContext.displayName = "Fetchers";
302
+ }
299
303
  //#endregion
300
304
  ////////////////////////////////////////////////////////////////////////////////
301
305
  //#region Components
@@ -358,6 +362,10 @@ function RouterProvider(_ref) {
358
362
  router,
359
363
  future
360
364
  } = _ref;
365
+ let {
366
+ fetcherContext,
367
+ fetcherData
368
+ } = useFetcherDataLayer();
361
369
  let [state, setStateImpl] = React.useState(router.state);
362
370
  let [pendingState, setPendingState] = React.useState();
363
371
  let [vtContext, setVtContext] = React.useState({
@@ -380,6 +388,11 @@ function RouterProvider(_ref) {
380
388
  let {
381
389
  unstable_viewTransitionOpts: viewTransitionOpts
382
390
  } = _ref2;
391
+ newState.fetchers.forEach((fetcher, key) => {
392
+ if (fetcher.data !== undefined) {
393
+ fetcherData.current.set(key, fetcher.data);
394
+ }
395
+ });
383
396
  if (!viewTransitionOpts || router.window == null || typeof router.window.document.startViewTransition !== "function") {
384
397
  // Mid-navigation state update, or startViewTransition isn't available
385
398
  optInStartTransition(() => setStateImpl(newState));
@@ -402,7 +415,7 @@ function RouterProvider(_ref) {
402
415
  nextLocation: viewTransitionOpts.nextLocation
403
416
  });
404
417
  }
405
- }, [optInStartTransition, transition, renderDfd, router.window]);
418
+ }, [router.window, transition, renderDfd, fetcherData, optInStartTransition]);
406
419
  // Need to use a layout effect here so we are subscribed early enough to
407
420
  // pick up on any render-driven redirects/navigations (useEffect/<Navigate>)
408
421
  React.useLayoutEffect(() => router.subscribe(setState), [router, setState]);
@@ -488,6 +501,8 @@ function RouterProvider(_ref) {
488
501
  value: dataRouterContext
489
502
  }, /*#__PURE__*/React.createElement(UNSAFE_DataRouterStateContext.Provider, {
490
503
  value: state
504
+ }, /*#__PURE__*/React.createElement(FetchersContext.Provider, {
505
+ value: fetcherContext
491
506
  }, /*#__PURE__*/React.createElement(ViewTransitionContext.Provider, {
492
507
  value: vtContext
493
508
  }, /*#__PURE__*/React.createElement(Router, {
@@ -498,7 +513,7 @@ function RouterProvider(_ref) {
498
513
  }, state.initialized ? /*#__PURE__*/React.createElement(DataRoutes, {
499
514
  routes: router.routes,
500
515
  state: state
501
- }) : fallbackElement)))), null);
516
+ }) : fallbackElement))))), null);
502
517
  }
503
518
  function DataRoutes(_ref3) {
504
519
  let {
@@ -767,34 +782,26 @@ if (process.env.NODE_ENV !== "production") {
767
782
  * requests, allowing components to add nicer UX to the page as the form is
768
783
  * submitted and returns with data.
769
784
  */
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) => {
785
+ const Form = /*#__PURE__*/React.forwardRef((_ref9, forwardedRef) => {
781
786
  let {
787
+ fetcherKey,
788
+ navigate,
782
789
  reloadDocument,
783
790
  replace,
784
791
  state,
785
792
  method = defaultMethod,
786
793
  action,
787
794
  onSubmit,
788
- submit,
789
795
  relative,
790
796
  preventScrollReset,
791
797
  unstable_viewTransition
792
798
  } = _ref9,
793
799
  props = _objectWithoutPropertiesLoose(_ref9, _excluded3);
794
- let formMethod = method.toLowerCase() === "get" ? "get" : "post";
800
+ let submit = useSubmit();
795
801
  let formAction = useFormAction(action, {
796
802
  relative
797
803
  });
804
+ let formMethod = method.toLowerCase() === "get" ? "get" : "post";
798
805
  let submitHandler = event => {
799
806
  onSubmit && onSubmit(event);
800
807
  if (event.defaultPrevented) return;
@@ -802,7 +809,9 @@ const FormImpl = /*#__PURE__*/React.forwardRef((_ref9, forwardedRef) => {
802
809
  let submitter = event.nativeEvent.submitter;
803
810
  let submitMethod = (submitter == null ? void 0 : submitter.getAttribute("formmethod")) || method;
804
811
  submit(submitter || event.currentTarget, {
812
+ fetcherKey,
805
813
  method: submitMethod,
814
+ navigate,
806
815
  replace,
807
816
  state,
808
817
  relative,
@@ -818,7 +827,7 @@ const FormImpl = /*#__PURE__*/React.forwardRef((_ref9, forwardedRef) => {
818
827
  }, props));
819
828
  });
820
829
  if (process.env.NODE_ENV !== "production") {
821
- FormImpl.displayName = "FormImpl";
830
+ Form.displayName = "Form";
822
831
  }
823
832
  /**
824
833
  * This component will emulate the browser's scroll restoration on location
@@ -852,9 +861,11 @@ var DataRouterHook;
852
861
  })(DataRouterHook || (DataRouterHook = {}));
853
862
  var DataRouterStateHook;
854
863
  (function (DataRouterStateHook) {
864
+ DataRouterStateHook["UseFetcher"] = "useFetcher";
855
865
  DataRouterStateHook["UseFetchers"] = "useFetchers";
856
866
  DataRouterStateHook["UseScrollRestoration"] = "useScrollRestoration";
857
867
  })(DataRouterStateHook || (DataRouterStateHook = {}));
868
+ // Internal hooks
858
869
  function getDataRouterConsoleError(hookName) {
859
870
  return hookName + " must be used within a data router. See https://reactrouter.com/routers/picking-a-router.";
860
871
  }
@@ -868,6 +879,37 @@ function useDataRouterState(hookName) {
868
879
  !state ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, getDataRouterConsoleError(hookName)) : UNSAFE_invariant(false) : void 0;
869
880
  return state;
870
881
  }
882
+ function useFetcherDataLayer() {
883
+ let fetcherRefs = React.useRef(new Map());
884
+ let fetcherData = React.useRef(new Map());
885
+ let registerFetcher = React.useCallback(key => {
886
+ let count = fetcherRefs.current.get(key);
887
+ if (count == null) {
888
+ fetcherRefs.current.set(key, 1);
889
+ } else {
890
+ fetcherRefs.current.set(key, count + 1);
891
+ }
892
+ }, [fetcherRefs]);
893
+ let unregisterFetcher = React.useCallback(key => {
894
+ let count = fetcherRefs.current.get(key);
895
+ if (count == null || count <= 1) {
896
+ fetcherRefs.current.delete(key);
897
+ fetcherData.current.delete(key);
898
+ } else {
899
+ fetcherRefs.current.set(key, count - 1);
900
+ }
901
+ }, [fetcherData, fetcherRefs]);
902
+ let fetcherContext = React.useMemo(() => ({
903
+ fetcherData: fetcherData.current,
904
+ register: registerFetcher,
905
+ unregister: unregisterFetcher
906
+ }), [fetcherData, registerFetcher, unregisterFetcher]);
907
+ return {
908
+ fetcherContext,
909
+ fetcherData
910
+ };
911
+ }
912
+ // External hooks
871
913
  /**
872
914
  * Handles the click behavior for router `<Link>` components. This is useful if
873
915
  * you need to create custom `<Link>` components with the same click behavior we
@@ -930,6 +972,8 @@ function validateClientSideSubmission() {
930
972
  throw new Error("You are calling submit during the server render. " + "Try calling submit within a `useEffect` or callback instead.");
931
973
  }
932
974
  }
975
+ let fetcherId = 0;
976
+ let getUniqueFetcherId = () => "__" + String(++fetcherId) + "__";
933
977
  /**
934
978
  * Returns a function that may be used to programmatically submit a form (or
935
979
  * some arbitrary data) to the server.
@@ -954,50 +998,29 @@ function useSubmit() {
954
998
  formData,
955
999
  body
956
1000
  } = 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 = {};
1001
+ if (options.navigate === false) {
1002
+ let key = options.fetcherKey || getUniqueFetcherId();
1003
+ router.fetch(key, currentRouteId, options.action || action, {
1004
+ preventScrollReset: options.preventScrollReset,
1005
+ formData,
1006
+ body,
1007
+ formMethod: options.method || method,
1008
+ formEncType: options.encType || encType
1009
+ });
1010
+ } else {
1011
+ router.navigate(options.action || action, {
1012
+ preventScrollReset: options.preventScrollReset,
1013
+ formData,
1014
+ body,
1015
+ formMethod: options.method || method,
1016
+ formEncType: options.encType || encType,
1017
+ replace: options.replace,
1018
+ state: options.state,
1019
+ fromRouteId: currentRouteId,
1020
+ unstable_viewTransition: options.unstable_viewTransition
1021
+ });
983
1022
  }
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]);
1023
+ }, [router, basename, currentRouteId]);
1001
1024
  }
1002
1025
  // v7: Eventually we should deprecate this entirely in favor of using the
1003
1026
  // router method directly?
@@ -1047,63 +1070,83 @@ function useFormAction(action, _temp2) {
1047
1070
  }
1048
1071
  return createPath(path);
1049
1072
  }
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
1073
  // TODO: (v7) Change the useFetcher generic default from `any` to `unknown`
1065
1074
  /**
1066
1075
  * Interacts with route loaders and actions without causing a navigation. Great
1067
1076
  * for any interaction that stays on the same page.
1068
1077
  */
1069
- function useFetcher() {
1078
+ function useFetcher(_temp3) {
1070
1079
  var _route$matches;
1080
+ let {
1081
+ key
1082
+ } = _temp3 === void 0 ? {} : _temp3;
1071
1083
  let {
1072
1084
  router
1073
1085
  } = useDataRouterContext(DataRouterHook.UseFetcher);
1086
+ let state = useDataRouterState(DataRouterStateHook.UseFetcher);
1087
+ let fetchersContext = React.useContext(FetchersContext);
1074
1088
  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
1089
  let routeId = (_route$matches = route.matches[route.matches.length - 1]) == null ? void 0 : _route$matches.route.id;
1090
+ !fetchersContext ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, "useFetcher must be used inside a FetchersContext") : UNSAFE_invariant(false) : void 0;
1091
+ !route ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, "useFetcher must be used inside a RouteContext") : UNSAFE_invariant(false) : void 0;
1077
1092
  !(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;
1093
+ // Fetcher key handling
1094
+ let [fetcherKey, setFetcherKey] = React.useState(key || "");
1095
+ if (!fetcherKey) {
1096
+ setFetcherKey(getUniqueFetcherId());
1097
+ }
1098
+ // Registration/cleanup
1099
+ let {
1100
+ fetcherData,
1101
+ register,
1102
+ unregister
1103
+ } = fetchersContext;
1104
+ React.useEffect(() => {
1105
+ register(fetcherKey);
1106
+ return () => {
1107
+ // Unregister from ref counting for the data layer
1108
+ unregister(fetcherKey);
1109
+ // Tell the router we've unmounted - if v7_fetcherPersist is enabled this
1110
+ // will not delete immediately but instead queue up a delete after the
1111
+ // fetcher returns to an `idle` state
1112
+ router.deleteFetcher(fetcherKey);
1113
+ };
1114
+ }, [router, fetcherKey, register, unregister]);
1115
+ // Fetcher additions
1116
+ let load = React.useCallback(href => {
1085
1117
  !routeId ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, "No routeId available for fetcher.load()") : UNSAFE_invariant(false) : void 0;
1086
1118
  router.fetch(fetcherKey, routeId, href);
1087
- });
1088
- let submit = useSubmitFetcher(fetcherKey, routeId);
1089
- let fetcher = router.getFetcher(fetcherKey);
1119
+ }, [fetcherKey, routeId, router]);
1120
+ let submitImpl = useSubmit();
1121
+ let submit = React.useCallback((target, opts) => {
1122
+ submitImpl(target, _extends({}, opts, {
1123
+ navigate: false,
1124
+ fetcherKey
1125
+ }));
1126
+ }, [fetcherKey, submitImpl]);
1127
+ let FetcherForm = React.useMemo(() => {
1128
+ let FetcherForm = /*#__PURE__*/React.forwardRef((props, ref) => {
1129
+ return /*#__PURE__*/React.createElement(Form, _extends({}, props, {
1130
+ navigate: false,
1131
+ fetcherKey: fetcherKey,
1132
+ ref: ref
1133
+ }));
1134
+ });
1135
+ if (process.env.NODE_ENV !== "production") {
1136
+ FetcherForm.displayName = "fetcher.Form";
1137
+ }
1138
+ return FetcherForm;
1139
+ }, [fetcherKey]);
1140
+ // Exposed FetcherWithComponents
1141
+ let fetcher = state.fetchers.get(fetcherKey) || IDLE_FETCHER;
1142
+ let data = fetcherData.get(fetcherKey);
1090
1143
  let fetcherWithComponents = React.useMemo(() => _extends({
1091
- Form,
1144
+ Form: FetcherForm,
1092
1145
  submit,
1093
1146
  load
1094
- }, fetcher), [fetcher, Form, submit, load]);
1095
- 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.
1099
- return () => {
1100
- if (!router) {
1101
- console.warn("No router available to clean up from useFetcher()");
1102
- return;
1103
- }
1104
- router.deleteFetcher(fetcherKey);
1105
- };
1106
- }, [router, fetcherKey]);
1147
+ }, fetcher, {
1148
+ data
1149
+ }), [FetcherForm, submit, load, fetcher, data]);
1107
1150
  return fetcherWithComponents;
1108
1151
  }
1109
1152
  /**
@@ -1112,18 +1155,23 @@ function useFetcher() {
1112
1155
  */
1113
1156
  function useFetchers() {
1114
1157
  let state = useDataRouterState(DataRouterStateHook.UseFetchers);
1115
- return [...state.fetchers.values()];
1158
+ return Array.from(state.fetchers.entries()).map(_ref11 => {
1159
+ let [key, fetcher] = _ref11;
1160
+ return _extends({}, fetcher, {
1161
+ key
1162
+ });
1163
+ });
1116
1164
  }
1117
1165
  const SCROLL_RESTORATION_STORAGE_KEY = "react-router-scroll-positions";
1118
1166
  let savedScrollPositions = {};
1119
1167
  /**
1120
1168
  * When rendered inside a RouterProvider, will restore scroll positions on navigations
1121
1169
  */
1122
- function useScrollRestoration(_temp3) {
1170
+ function useScrollRestoration(_temp4) {
1123
1171
  let {
1124
1172
  getKey,
1125
1173
  storageKey
1126
- } = _temp3 === void 0 ? {} : _temp3;
1174
+ } = _temp4 === void 0 ? {} : _temp4;
1127
1175
  let {
1128
1176
  router
1129
1177
  } = useDataRouterContext(DataRouterHook.UseScrollRestoration);
@@ -1261,11 +1309,11 @@ function usePageHide(callback, options) {
1261
1309
  * very incorrectly in some cases) across browsers if user click addition
1262
1310
  * back/forward navigations while the confirm is open. Use at your own risk.
1263
1311
  */
1264
- function usePrompt(_ref11) {
1312
+ function usePrompt(_ref12) {
1265
1313
  let {
1266
1314
  when,
1267
1315
  message
1268
- } = _ref11;
1316
+ } = _ref12;
1269
1317
  let blocker = unstable_useBlocker(when);
1270
1318
  React.useEffect(() => {
1271
1319
  if (blocker.state === "blocked") {