react-router 6.8.2 → 6.9.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
- * React Router v6.8.2
2
+ * React Router v6.9.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -34,23 +34,6 @@
34
34
 
35
35
  var React__namespace = /*#__PURE__*/_interopNamespace(React);
36
36
 
37
- function _extends() {
38
- _extends = Object.assign ? Object.assign.bind() : function (target) {
39
- for (var i = 1; i < arguments.length; i++) {
40
- var source = arguments[i];
41
-
42
- for (var key in source) {
43
- if (Object.prototype.hasOwnProperty.call(source, key)) {
44
- target[key] = source[key];
45
- }
46
- }
47
- }
48
-
49
- return target;
50
- };
51
- return _extends.apply(this, arguments);
52
- }
53
-
54
37
  /**
55
38
  * Copyright (c) Facebook, Inc. and its affiliates.
56
39
  *
@@ -274,6 +257,23 @@
274
257
  RouteErrorContext.displayName = "RouteError";
275
258
  }
276
259
 
260
+ function _extends() {
261
+ _extends = Object.assign ? Object.assign.bind() : function (target) {
262
+ for (var i = 1; i < arguments.length; i++) {
263
+ var source = arguments[i];
264
+
265
+ for (var key in source) {
266
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
267
+ target[key] = source[key];
268
+ }
269
+ }
270
+ }
271
+
272
+ return target;
273
+ };
274
+ return _extends.apply(this, arguments);
275
+ }
276
+
277
277
  /**
278
278
  * Returns the full href for the given "to" value. This is useful for building
279
279
  * custom links that are also accessible and preserve right-click behavior.
@@ -401,7 +401,7 @@
401
401
  options = {};
402
402
  }
403
403
 
404
- router.warning(activeRef.current, "You should call navigate() in a React.useEffect(), not when " + "your component is first rendered.") ;
404
+ router.UNSAFE_warning(activeRef.current, "You should call navigate() in a React.useEffect(), not when " + "your component is first rendered.") ;
405
405
  if (!activeRef.current) return;
406
406
 
407
407
  if (typeof to === "number") {
@@ -554,8 +554,8 @@
554
554
  });
555
555
 
556
556
  {
557
- router.warning(parentRoute || matches != null, "No routes matched location \"" + location.pathname + location.search + location.hash + "\" ") ;
558
- router.warning(matches == null || matches[matches.length - 1].route.element !== undefined, "Matched leaf route at location \"" + location.pathname + location.search + location.hash + "\" does not have an element. " + "This means it will render an <Outlet /> with a null value by default resulting in an \"empty\" page.") ;
557
+ router.UNSAFE_warning(parentRoute || matches != null, "No routes matched location \"" + location.pathname + location.search + location.hash + "\" ") ;
558
+ router.UNSAFE_warning(matches == null || matches[matches.length - 1].route.element !== undefined || matches[matches.length - 1].route.Component !== 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.") ;
559
559
  }
560
560
 
561
561
  let renderedMatches = _renderMatches(matches && matches.map(match => Object.assign({}, match, {
@@ -587,7 +587,7 @@
587
587
  return renderedMatches;
588
588
  }
589
589
 
590
- function DefaultErrorElement() {
590
+ function DefaultErrorComponent() {
591
591
  let error = useRouteError();
592
592
  let message = router.isRouteErrorResponse(error) ? error.status + " " + error.statusText : error instanceof Error ? error.message : JSON.stringify(error);
593
593
  let stack = error instanceof Error ? error.stack : null;
@@ -605,7 +605,7 @@
605
605
  {
606
606
  devInfo = /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement("p", null, "\uD83D\uDCBF Hey developer \uD83D\uDC4B"), /*#__PURE__*/React__namespace.createElement("p", null, "You can provide a way better UX than this when your app throws errors by providing your own\xA0", /*#__PURE__*/React__namespace.createElement("code", {
607
607
  style: codeStyles
608
- }, "errorElement"), " props on\xA0", /*#__PURE__*/React__namespace.createElement("code", {
608
+ }, "ErrorBoundary"), " prop on\xA0", /*#__PURE__*/React__namespace.createElement("code", {
609
609
  style: codeStyles
610
610
  }, "<Route>")));
611
611
  }
@@ -684,7 +684,7 @@
684
684
  let dataRouterContext = React__namespace.useContext(DataRouterContext); // Track how deep we got in our render pass to emulate SSR componentDidCatch
685
685
  // in a DataStaticRouter
686
686
 
687
- if (dataRouterContext && dataRouterContext.static && dataRouterContext.staticContext && match.route.errorElement) {
687
+ if (dataRouterContext && dataRouterContext.static && dataRouterContext.staticContext && (match.route.errorElement || match.route.ErrorBoundary)) {
688
688
  dataRouterContext.staticContext._deepestRenderedBoundaryId = match.route.id;
689
689
  }
690
690
 
@@ -721,21 +721,45 @@
721
721
  return renderedMatches.reduceRight((outlet, match, index) => {
722
722
  let error = match.route.id ? errors == null ? void 0 : errors[match.route.id] : null; // Only data routers handle errors
723
723
 
724
- let errorElement = dataRouterState ? match.route.errorElement || /*#__PURE__*/React__namespace.createElement(DefaultErrorElement, null) : null;
724
+ let errorElement = null;
725
+
726
+ if (dataRouterState) {
727
+ if (match.route.ErrorBoundary) {
728
+ errorElement = /*#__PURE__*/React__namespace.createElement(match.route.ErrorBoundary, null);
729
+ } else if (match.route.errorElement) {
730
+ errorElement = match.route.errorElement;
731
+ } else {
732
+ errorElement = /*#__PURE__*/React__namespace.createElement(DefaultErrorComponent, null);
733
+ }
734
+ }
735
+
725
736
  let matches = parentMatches.concat(renderedMatches.slice(0, index + 1));
726
737
 
727
- let getChildren = () => /*#__PURE__*/React__namespace.createElement(RenderedRoute, {
728
- match: match,
729
- routeContext: {
730
- outlet,
731
- matches
738
+ let getChildren = () => {
739
+ let children = outlet;
740
+
741
+ if (error) {
742
+ children = errorElement;
743
+ } else if (match.route.Component) {
744
+ children = /*#__PURE__*/React__namespace.createElement(match.route.Component, null);
745
+ } else if (match.route.element) {
746
+ children = match.route.element;
732
747
  }
733
- }, error ? errorElement : match.route.element !== undefined ? match.route.element : outlet); // Only wrap in an error boundary within data router usages when we have an
734
- // errorElement on this route. Otherwise let it bubble up to an ancestor
735
- // errorElement
748
+
749
+ return /*#__PURE__*/React__namespace.createElement(RenderedRoute, {
750
+ match: match,
751
+ routeContext: {
752
+ outlet,
753
+ matches
754
+ },
755
+ children: children
756
+ });
757
+ }; // Only wrap in an error boundary within data router usages when we have an
758
+ // ErrorBoundary/errorElement on this route. Otherwise let it bubble up to
759
+ // an ancestor ErrorBoundary/errorElement
736
760
 
737
761
 
738
- return dataRouterState && (match.route.errorElement || index === 0) ? /*#__PURE__*/React__namespace.createElement(RenderErrorBoundary, {
762
+ return dataRouterState && (match.route.ErrorBoundary || match.route.errorElement || index === 0) ? /*#__PURE__*/React__namespace.createElement(RenderErrorBoundary, {
739
763
  location: dataRouterState.location,
740
764
  component: errorElement,
741
765
  error: error,
@@ -757,6 +781,7 @@
757
781
  var DataRouterStateHook;
758
782
 
759
783
  (function (DataRouterStateHook) {
784
+ DataRouterStateHook["UseBlocker"] = "useBlocker";
760
785
  DataRouterStateHook["UseLoaderData"] = "useLoaderData";
761
786
  DataRouterStateHook["UseActionData"] = "useActionData";
762
787
  DataRouterStateHook["UseRouteError"] = "useRouteError";
@@ -880,7 +905,7 @@
880
905
  /**
881
906
  * Returns the nearest ancestor Route error, which could be a loader/action
882
907
  * error or a render error. This is intended to be called from your
883
- * errorElement to display a proper error message.
908
+ * ErrorBoundary/errorElement to display a proper error message.
884
909
  */
885
910
 
886
911
  function useRouteError() {
@@ -926,21 +951,24 @@
926
951
  let {
927
952
  router
928
953
  } = useDataRouterContext(DataRouterHook.UseBlocker);
954
+ let state = useDataRouterState(DataRouterStateHook.UseBlocker);
929
955
  let [blockerKey] = React__namespace.useState(() => String(++blockerId));
930
956
  let blockerFunction = React__namespace.useCallback(args => {
931
957
  return typeof shouldBlock === "function" ? !!shouldBlock(args) : !!shouldBlock;
932
958
  }, [shouldBlock]);
933
959
  let blocker = router.getBlocker(blockerKey, blockerFunction); // Cleanup on unmount
934
960
 
935
- React__namespace.useEffect(() => () => router.deleteBlocker(blockerKey), [router, blockerKey]);
936
- return blocker;
961
+ React__namespace.useEffect(() => () => router.deleteBlocker(blockerKey), [router, blockerKey]); // Prefer the blocker from state since DataRouterContext is memoized so this
962
+ // ensures we update on blocker state updates
963
+
964
+ return state.blockers.get(blockerKey) || blocker;
937
965
  }
938
966
  const alreadyWarned = {};
939
967
 
940
968
  function warningOnce(key, cond, message) {
941
969
  if (!cond && !alreadyWarned[key]) {
942
970
  alreadyWarned[key] = true;
943
- router.warning(false, message) ;
971
+ router.UNSAFE_warning(false, message) ;
944
972
  }
945
973
  }
946
974
 
@@ -952,11 +980,12 @@
952
980
  fallbackElement,
953
981
  router
954
982
  } = _ref;
955
- // Sync router state to our component state to force re-renders
956
- let state = useSyncExternalStore(router.subscribe, () => router.state, // We have to provide this so React@18 doesn't complain during hydration,
983
+ let getState = React__namespace.useCallback(() => router.state, [router]); // Sync router state to our component state to force re-renders
984
+
985
+ let state = useSyncExternalStore(router.subscribe, getState, // We have to provide this so React@18 doesn't complain during hydration,
957
986
  // but we pass our serialized hydration data into the router so state here
958
987
  // is already synced with what the server saw
959
- () => router.state);
988
+ getState);
960
989
  let navigator = React__namespace.useMemo(() => {
961
990
  return {
962
991
  createHref: router.createHref,
@@ -973,7 +1002,13 @@
973
1002
  })
974
1003
  };
975
1004
  }, [router]);
976
- let basename = router.basename || "/"; // The fragment and {null} here are important! We need them to keep React 18's
1005
+ let basename = router.basename || "/";
1006
+ let dataRouterContext = React__namespace.useMemo(() => ({
1007
+ router,
1008
+ navigator,
1009
+ static: false,
1010
+ basename
1011
+ }), [router, navigator, basename]); // The fragment and {null} here are important! We need them to keep React 18's
977
1012
  // useId happy when we are server-rendering since we may have a <script> here
978
1013
  // containing the hydrated server-side staticContext (from StaticRouterProvider).
979
1014
  // useId relies on the component tree structure to generate deterministic id's
@@ -981,13 +1016,7 @@
981
1016
  // we don't need the <script> tag
982
1017
 
983
1018
  return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(DataRouterContext.Provider, {
984
- value: {
985
- router,
986
- navigator,
987
- static: false,
988
- // Do we need this?
989
- basename
990
- }
1019
+ value: dataRouterContext
991
1020
  }, /*#__PURE__*/React__namespace.createElement(DataRouterStateContext.Provider, {
992
1021
  value: state
993
1022
  }, /*#__PURE__*/React__namespace.createElement(Router, {
@@ -1054,7 +1083,7 @@
1054
1083
  !useInRouterContext() ? router.UNSAFE_invariant(false, // TODO: This error is probably because they somehow have 2 versions of
1055
1084
  // the router loaded. We can help them understand how to avoid that.
1056
1085
  "<Navigate> may be used only in the context of a <Router> component.") : void 0;
1057
- router.warning(!React__namespace.useContext(NavigationContext).static, "<Navigate> must not be used on the initial render in a <StaticRouter>. " + "This is a no-op, but you should modify your code so the <Navigate> is " + "only ever rendered in response to some user interaction or state change.") ;
1086
+ router.UNSAFE_warning(!React__namespace.useContext(NavigationContext).static, "<Navigate> must not be used on the initial render in a <StaticRouter>. " + "This is a no-op, but you should modify your code so the <Navigate> is " + "only ever rendered in response to some user interaction or state change.") ;
1058
1087
  let dataRouterState = React__namespace.useContext(DataRouterStateContext);
1059
1088
  let navigate = useNavigate();
1060
1089
  React__namespace.useEffect(() => {
@@ -1131,7 +1160,7 @@
1131
1160
  state = null,
1132
1161
  key = "default"
1133
1162
  } = locationProp;
1134
- let location = React__namespace.useMemo(() => {
1163
+ let locationContext = React__namespace.useMemo(() => {
1135
1164
  let trailingPathname = router.stripBasename(pathname, basename);
1136
1165
 
1137
1166
  if (trailingPathname == null) {
@@ -1139,16 +1168,19 @@
1139
1168
  }
1140
1169
 
1141
1170
  return {
1142
- pathname: trailingPathname,
1143
- search,
1144
- hash,
1145
- state,
1146
- key
1171
+ location: {
1172
+ pathname: trailingPathname,
1173
+ search,
1174
+ hash,
1175
+ state,
1176
+ key
1177
+ },
1178
+ navigationType
1147
1179
  };
1148
- }, [basename, pathname, search, hash, state, key]);
1149
- router.warning(location != null, "<Router basename=\"" + basename + "\"> is not able to match the URL " + ("\"" + pathname + search + hash + "\" because it does not start with the ") + "basename, so the <Router> won't render anything.") ;
1180
+ }, [basename, pathname, search, hash, state, key, navigationType]);
1181
+ router.UNSAFE_warning(locationContext != null, "<Router basename=\"" + basename + "\"> is not able to match the URL " + ("\"" + pathname + search + hash + "\" because it does not start with the ") + "basename, so the <Router> won't render anything.") ;
1150
1182
 
1151
- if (location == null) {
1183
+ if (locationContext == null) {
1152
1184
  return null;
1153
1185
  }
1154
1186
 
@@ -1156,10 +1188,7 @@
1156
1188
  value: navigationContext
1157
1189
  }, /*#__PURE__*/React__namespace.createElement(LocationContext.Provider, {
1158
1190
  children: children,
1159
- value: {
1160
- location,
1161
- navigationType
1162
- }
1191
+ value: locationContext
1163
1192
  }));
1164
1193
  }
1165
1194
 
@@ -1356,14 +1385,17 @@
1356
1385
  id: element.props.id || treePath.join("-"),
1357
1386
  caseSensitive: element.props.caseSensitive,
1358
1387
  element: element.props.element,
1388
+ Component: element.props.Component,
1359
1389
  index: element.props.index,
1360
1390
  path: element.props.path,
1361
1391
  loader: element.props.loader,
1362
1392
  action: element.props.action,
1363
1393
  errorElement: element.props.errorElement,
1364
- hasErrorBoundary: element.props.errorElement != null,
1394
+ ErrorBoundary: element.props.ErrorBoundary,
1395
+ hasErrorBoundary: element.props.ErrorBoundary != null || element.props.errorElement != null,
1365
1396
  shouldRevalidate: element.props.shouldRevalidate,
1366
- handle: element.props.handle
1397
+ handle: element.props.handle,
1398
+ lazy: element.props.lazy
1367
1399
  };
1368
1400
 
1369
1401
  if (element.props.children) {
@@ -1381,26 +1413,21 @@
1381
1413
  function renderMatches(matches) {
1382
1414
  return _renderMatches(matches);
1383
1415
  }
1384
- /**
1385
- * @private
1386
- * Walk the route tree and add hasErrorBoundary if it's not provided, so that
1387
- * users providing manual route arrays can just specify errorElement
1388
- */
1389
-
1390
- function enhanceManualRouteObjects(routes) {
1391
- return routes.map(route => {
1392
- let routeClone = _extends({}, route);
1393
1416
 
1394
- if (routeClone.hasErrorBoundary == null) {
1395
- routeClone.hasErrorBoundary = routeClone.errorElement != null;
1417
+ function detectErrorBoundary(route) {
1418
+ {
1419
+ if (route.Component && route.element) {
1420
+ router.UNSAFE_warning(false, "You should not include both `Component` and `element` on your route - " + "`element` will be ignored.") ;
1396
1421
  }
1397
1422
 
1398
- if (routeClone.children) {
1399
- routeClone.children = enhanceManualRouteObjects(routeClone.children);
1423
+ if (route.ErrorBoundary && route.errorElement) {
1424
+ router.UNSAFE_warning(false, "You should not include both `ErrorBoundary` and `errorElement` on your route - " + "`errorElement` will be ignored.") ;
1400
1425
  }
1426
+ } // Note: this check also occurs in createRoutesFromChildren so update
1427
+ // there if you change this
1401
1428
 
1402
- return routeClone;
1403
- });
1429
+
1430
+ return Boolean(route.ErrorBoundary) || Boolean(route.errorElement);
1404
1431
  }
1405
1432
 
1406
1433
  function createMemoryRouter(routes, opts) {
@@ -1411,7 +1438,8 @@
1411
1438
  initialIndex: opts == null ? void 0 : opts.initialIndex
1412
1439
  }),
1413
1440
  hydrationData: opts == null ? void 0 : opts.hydrationData,
1414
- routes: enhanceManualRouteObjects(routes)
1441
+ routes,
1442
+ detectErrorBoundary
1415
1443
  }).initialize();
1416
1444
  } ///////////////////////////////////////////////////////////////////////////////
1417
1445
 
@@ -1476,7 +1504,7 @@
1476
1504
  exports.UNSAFE_LocationContext = LocationContext;
1477
1505
  exports.UNSAFE_NavigationContext = NavigationContext;
1478
1506
  exports.UNSAFE_RouteContext = RouteContext;
1479
- exports.UNSAFE_enhanceManualRouteObjects = enhanceManualRouteObjects;
1507
+ exports.UNSAFE_detectErrorBoundary = detectErrorBoundary;
1480
1508
  exports.createMemoryRouter = createMemoryRouter;
1481
1509
  exports.createRoutesFromChildren = createRoutesFromChildren;
1482
1510
  exports.createRoutesFromElements = createRoutesFromChildren;