react-router 6.0.0-beta.6 → 6.0.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.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * React Router v6.0.0-beta.6
2
+ * React Router v6.0.1
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -67,10 +67,7 @@ const LocationContext = /*#__PURE__*/createContext(null);
67
67
 
68
68
  const RouteContext = /*#__PURE__*/createContext({
69
69
  outlet: null,
70
- params: {},
71
- pathname: "/",
72
- pathnameBase: "/",
73
- route: null
70
+ matches: []
74
71
  });
75
72
 
76
73
  {
@@ -83,7 +80,7 @@ const RouteContext = /*#__PURE__*/createContext({
83
80
  /**
84
81
  * A <Router> that stores all entries in memory.
85
82
  *
86
- * @see https://reactrouter.com/api/MemoryRouter
83
+ * @see https://reactrouter.com/docs/en/v6/api#memoryrouter
87
84
  */
88
85
  function MemoryRouter({
89
86
  basename,
@@ -109,8 +106,8 @@ function MemoryRouter({
109
106
  return /*#__PURE__*/createElement(Router, {
110
107
  basename: basename,
111
108
  children: children,
112
- action: state.action,
113
109
  location: state.location,
110
+ navigationType: state.action,
114
111
  navigator: history
115
112
  });
116
113
  }
@@ -122,7 +119,7 @@ function MemoryRouter({
122
119
  * able to use hooks. In functional components, we recommend you use the
123
120
  * `useNavigate` hook instead.
124
121
  *
125
- * @see https://reactrouter.com/api/Navigate
122
+ * @see https://reactrouter.com/docs/en/v6/api#navigate
126
123
  */
127
124
  function Navigate({
128
125
  to,
@@ -146,7 +143,7 @@ function Navigate({
146
143
  /**
147
144
  * Renders the child route's element, if there is one.
148
145
  *
149
- * @see https://reactrouter.com/api/Outlet
146
+ * @see https://reactrouter.com/docs/en/v6/api#outlet
150
147
  */
151
148
  function Outlet(_props) {
152
149
  return useOutlet();
@@ -155,7 +152,7 @@ function Outlet(_props) {
155
152
  /**
156
153
  * Declares an element that should be rendered at a certain URL path.
157
154
  *
158
- * @see https://reactrouter.com/api/Route
155
+ * @see https://reactrouter.com/docs/en/v6/api#route
159
156
  */
160
157
  function Route(_props) {
161
158
  invariant(false, `A <Route> is only ever to be used as the child of <Routes> element, ` + `never rendered directly. Please wrap your <Route> in a <Routes>.`) ;
@@ -168,13 +165,13 @@ function Route(_props) {
168
165
  * router that is more specific to your environment such as a <BrowserRouter>
169
166
  * in web browsers or a <StaticRouter> for server rendering.
170
167
  *
171
- * @see https://reactrouter.com/api/Router
168
+ * @see https://reactrouter.com/docs/en/v6/api#router
172
169
  */
173
170
  function Router({
174
- action = Action.Pop,
175
171
  basename: basenameProp = "/",
176
172
  children = null,
177
173
  location: locationProp,
174
+ navigationType = Action.Pop,
178
175
  navigator,
179
176
  static: staticProp = false
180
177
  }) {
@@ -223,8 +220,8 @@ function Router({
223
220
  }, /*#__PURE__*/createElement(LocationContext.Provider, {
224
221
  children: children,
225
222
  value: {
226
- action,
227
- location
223
+ location,
224
+ navigationType
228
225
  }
229
226
  }));
230
227
  }
@@ -233,7 +230,7 @@ function Router({
233
230
  * A container for a nested tree of <Route> elements that renders the branch
234
231
  * that best matches the current location.
235
232
  *
236
- * @see https://reactrouter.com/api/Routes
233
+ * @see https://reactrouter.com/docs/en/v6/api#routes
237
234
  */
238
235
  function Routes({
239
236
  children,
@@ -244,44 +241,11 @@ function Routes({
244
241
  // HOOKS
245
242
  ///////////////////////////////////////////////////////////////////////////////
246
243
 
247
- /**
248
- * Blocks all navigation attempts. This is useful for preventing the page from
249
- * changing until some condition is met, like saving form data.
250
- *
251
- * @see https://reactrouter.com/api/useBlocker
252
- */
253
-
254
- function useBlocker(blocker, when = true) {
255
- !useInRouterContext() ? invariant(false, // TODO: This error is probably because they somehow have 2 versions of the
256
- // router loaded. We can help them understand how to avoid that.
257
- `useBlocker() may be used only in the context of a <Router> component.`) : void 0;
258
- let {
259
- navigator
260
- } = useContext(NavigationContext);
261
- useEffect(() => {
262
- if (!when) return;
263
- let unblock = navigator.block(tx => {
264
- let autoUnblockingTx = { ...tx,
265
-
266
- retry() {
267
- // Automatically unblock the transition so it can play all the way
268
- // through before retrying it. TODO: Figure out how to re-enable
269
- // this block if the transition is cancelled for some reason.
270
- unblock();
271
- tx.retry();
272
- }
273
-
274
- };
275
- blocker(autoUnblockingTx);
276
- });
277
- return unblock;
278
- }, [navigator, blocker, when]);
279
- }
280
244
  /**
281
245
  * Returns the full href for the given "to" value. This is useful for building
282
246
  * custom links that are also accessible and preserve right-click behavior.
283
247
  *
284
- * @see https://reactrouter.com/api/useHref
248
+ * @see https://reactrouter.com/docs/en/v6/api#usehref
285
249
  */
286
250
 
287
251
  function useHref(to) {
@@ -292,20 +256,29 @@ function useHref(to) {
292
256
  basename,
293
257
  navigator
294
258
  } = useContext(NavigationContext);
295
- let path = useResolvedPath(to);
259
+ let {
260
+ hash,
261
+ pathname,
262
+ search
263
+ } = useResolvedPath(to);
264
+ let joinedPathname = pathname;
296
265
 
297
266
  if (basename !== "/") {
298
267
  let toPathname = getToPathname(to);
299
268
  let endsWithSlash = toPathname != null && toPathname.endsWith("/");
300
- path.pathname = path.pathname === "/" ? basename + (endsWithSlash ? "/" : "") : joinPaths([basename, path.pathname]);
269
+ joinedPathname = pathname === "/" ? basename + (endsWithSlash ? "/" : "") : joinPaths([basename, pathname]);
301
270
  }
302
271
 
303
- return navigator.createHref(path);
272
+ return navigator.createHref({
273
+ pathname: joinedPathname,
274
+ search,
275
+ hash
276
+ });
304
277
  }
305
278
  /**
306
279
  * Returns true if this component is a descendant of a <Router>.
307
280
  *
308
- * @see https://reactrouter.com/api/useInRouterContext
281
+ * @see https://reactrouter.com/docs/en/v6/api#useinroutercontext
309
282
  */
310
283
 
311
284
  function useInRouterContext() {
@@ -319,7 +292,7 @@ function useInRouterContext() {
319
292
  * "routing" in your app, and we'd like to know what your use case is. We may
320
293
  * be able to provide something higher-level to better suit your needs.
321
294
  *
322
- * @see https://reactrouter.com/api/useLocation
295
+ * @see https://reactrouter.com/docs/en/v6/api#uselocation
323
296
  */
324
297
 
325
298
  function useLocation() {
@@ -328,12 +301,22 @@ function useLocation() {
328
301
  `useLocation() may be used only in the context of a <Router> component.`) : void 0;
329
302
  return useContext(LocationContext).location;
330
303
  }
304
+ /**
305
+ * Returns the current navigation action which describes how the router came to
306
+ * the current location, either by a pop, push, or replace on the history stack.
307
+ *
308
+ * @see https://reactrouter.com/docs/en/v6/api#usenavigationtype
309
+ */
310
+
311
+ function useNavigationType() {
312
+ return useContext(LocationContext).navigationType;
313
+ }
331
314
  /**
332
315
  * Returns true if the URL for the given "to" value matches the current URL.
333
316
  * This is useful for components that need to know "active" state, e.g.
334
317
  * <NavLink>.
335
318
  *
336
- * @see https://reactrouter.com/api/useMatch
319
+ * @see https://reactrouter.com/docs/en/v6/api#usematch
337
320
  */
338
321
 
339
322
  function useMatch(pattern) {
@@ -350,7 +333,7 @@ function useMatch(pattern) {
350
333
  * Returns an imperative method for changing the location. Used by <Link>s, but
351
334
  * may also be used by other elements to change the location.
352
335
  *
353
- * @see https://reactrouter.com/api/useNavigate
336
+ * @see https://reactrouter.com/docs/en/v6/api#usenavigate
354
337
  */
355
338
  function useNavigate() {
356
339
  !useInRouterContext() ? invariant(false, // TODO: This error is probably because they somehow have 2 versions of the
@@ -361,11 +344,12 @@ function useNavigate() {
361
344
  navigator
362
345
  } = useContext(NavigationContext);
363
346
  let {
364
- pathname: routePathname
347
+ matches
365
348
  } = useContext(RouteContext);
366
349
  let {
367
350
  pathname: locationPathname
368
351
  } = useLocation();
352
+ let routePathnamesJson = JSON.stringify(matches.map(match => match.pathnameBase));
369
353
  let activeRef = useRef(false);
370
354
  useEffect(() => {
371
355
  activeRef.current = true;
@@ -379,21 +363,21 @@ function useNavigate() {
379
363
  return;
380
364
  }
381
365
 
382
- let path = resolveTo(to, routePathname, locationPathname);
366
+ let path = resolveTo(to, JSON.parse(routePathnamesJson), locationPathname);
383
367
 
384
368
  if (basename !== "/") {
385
369
  path.pathname = joinPaths([basename, path.pathname]);
386
370
  }
387
371
 
388
372
  (!!options.replace ? navigator.replace : navigator.push)(path, options.state);
389
- }, [basename, navigator, routePathname, locationPathname]);
373
+ }, [basename, navigator, routePathnamesJson, locationPathname]);
390
374
  return navigate;
391
375
  }
392
376
  /**
393
377
  * Returns the element for the child route at this level of the route
394
378
  * hierarchy. Used internally by <Outlet> to render child routes.
395
379
  *
396
- * @see https://reactrouter.com/api/useOutlet
380
+ * @see https://reactrouter.com/docs/en/v6/api#useoutlet
397
381
  */
398
382
 
399
383
  function useOutlet() {
@@ -403,26 +387,31 @@ function useOutlet() {
403
387
  * Returns an object of key/value pairs of the dynamic params from the current
404
388
  * URL that were matched by the route path.
405
389
  *
406
- * @see https://reactrouter.com/api/useParams
390
+ * @see https://reactrouter.com/docs/en/v6/api#useparams
407
391
  */
408
392
 
409
393
  function useParams() {
410
- return useContext(RouteContext).params;
394
+ let {
395
+ matches
396
+ } = useContext(RouteContext);
397
+ let routeMatch = matches[matches.length - 1];
398
+ return routeMatch ? routeMatch.params : {};
411
399
  }
412
400
  /**
413
401
  * Resolves the pathname of the given `to` value against the current location.
414
402
  *
415
- * @see https://reactrouter.com/api/useResolvedPath
403
+ * @see https://reactrouter.com/docs/en/v6/api#useresolvedpath
416
404
  */
417
405
 
418
406
  function useResolvedPath(to) {
419
407
  let {
420
- pathname: routePathname
408
+ matches
421
409
  } = useContext(RouteContext);
422
410
  let {
423
411
  pathname: locationPathname
424
412
  } = useLocation();
425
- return useMemo(() => resolveTo(to, routePathname, locationPathname), [to, routePathname, locationPathname]);
413
+ let routePathnamesJson = JSON.stringify(matches.map(match => match.pathnameBase));
414
+ return useMemo(() => resolveTo(to, JSON.parse(routePathnamesJson), locationPathname), [to, routePathnamesJson, locationPathname]);
426
415
  }
427
416
  /**
428
417
  * Returns the element of the route that matched the current location, prepared
@@ -430,7 +419,7 @@ function useResolvedPath(to) {
430
419
  * elements in the tree must render an <Outlet> to render their child route's
431
420
  * element.
432
421
  *
433
- * @see https://reactrouter.com/api/useRoutes
422
+ * @see https://reactrouter.com/docs/en/v6/api#useroutes
434
423
  */
435
424
 
436
425
  function useRoutes(routes, locationArg) {
@@ -438,11 +427,13 @@ function useRoutes(routes, locationArg) {
438
427
  // router loaded. We can help them understand how to avoid that.
439
428
  `useRoutes() may be used only in the context of a <Router> component.`) : void 0;
440
429
  let {
441
- params: parentParams,
442
- pathname: parentPathname,
443
- pathnameBase: parentPathnameBase,
444
- route: parentRoute
430
+ matches: parentMatches
445
431
  } = useContext(RouteContext);
432
+ let routeMatch = parentMatches[parentMatches.length - 1];
433
+ let parentParams = routeMatch ? routeMatch.params : {};
434
+ let parentPathname = routeMatch ? routeMatch.pathname : "/";
435
+ let parentPathnameBase = routeMatch ? routeMatch.pathnameBase : "/";
436
+ let parentRoute = routeMatch && routeMatch.route;
446
437
 
447
438
  {
448
439
  // You won't get a warning about 2 different <Routes> under a <Route>
@@ -488,13 +479,14 @@ function useRoutes(routes, locationArg) {
488
479
 
489
480
  {
490
481
  warning(parentRoute || matches != null, `No routes matched location "${location.pathname}${location.search}${location.hash}" `) ;
482
+ 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.`) ;
491
483
  }
492
484
 
493
- return renderMatches(matches && matches.map(match => Object.assign({}, match, {
485
+ return _renderMatches(matches && matches.map(match => Object.assign({}, match, {
494
486
  params: Object.assign({}, parentParams, match.params),
495
487
  pathname: joinPaths([parentPathnameBase, match.pathname]),
496
- pathnameBase: joinPaths([parentPathnameBase, match.pathnameBase])
497
- })));
488
+ pathnameBase: match.pathnameBase === "/" ? parentPathnameBase : joinPaths([parentPathnameBase, match.pathnameBase])
489
+ })), parentMatches);
498
490
  } ///////////////////////////////////////////////////////////////////////////////
499
491
  // UTILS
500
492
  ///////////////////////////////////////////////////////////////////////////////
@@ -504,7 +496,7 @@ function useRoutes(routes, locationArg) {
504
496
  * either a `<Route>` element or an array of them. Used internally by
505
497
  * `<Routes>` to create a route config from its children.
506
498
  *
507
- * @see https://reactrouter.com/api/createRoutesFromChildren
499
+ * @see https://reactrouter.com/docs/en/v6/api#createroutesfromchildren
508
500
  */
509
501
 
510
502
  function createRoutesFromChildren(children) {
@@ -522,6 +514,7 @@ function createRoutesFromChildren(children) {
522
514
  return;
523
515
  }
524
516
 
517
+ !(element.type === Route) ? invariant(false, `[${typeof element.type === "string" ? element.type : element.type.name}] is not a <Route> component. All component children of <Routes> must be a <Route> or <React.Fragment>`) : void 0;
525
518
  let route = {
526
519
  caseSensitive: element.props.caseSensitive,
527
520
  element: element.props.element,
@@ -544,7 +537,7 @@ function createRoutesFromChildren(children) {
544
537
  /**
545
538
  * Returns a path with params interpolated.
546
539
  *
547
- * @see https://reactrouter.com/api/generatePath
540
+ * @see https://reactrouter.com/docs/en/v6/api#generatepath
548
541
  */
549
542
  function generatePath(path, params = {}) {
550
543
  return path.replace(/:(\w+)/g, (_, key) => {
@@ -559,7 +552,7 @@ function generatePath(path, params = {}) {
559
552
  /**
560
553
  * Matches the given routes to a location and returns the match data.
561
554
  *
562
- * @see https://reactrouter.com/api/matchRoutes
555
+ * @see https://reactrouter.com/docs/en/v6/api#matchroutes
563
556
  */
564
557
  function matchRoutes(routes, locationArg, basename = "/") {
565
558
  let location = typeof locationArg === "string" ? parsePath(locationArg) : locationArg;
@@ -611,7 +604,7 @@ function flattenRoutes(routes, branches = [], parentsMeta = [], parentPath = "")
611
604
 
612
605
  branches.push({
613
606
  path,
614
- score: computeScore(path),
607
+ score: computeScore(path, route.index),
615
608
  routesMeta
616
609
  });
617
610
  });
@@ -624,14 +617,15 @@ function rankRouteBranches(branches) {
624
617
  }
625
618
 
626
619
  const paramRe = /^:\w+$/;
627
- const dynamicSegmentValue = 2;
620
+ const dynamicSegmentValue = 3;
621
+ const indexRouteValue = 2;
628
622
  const emptySegmentValue = 1;
629
623
  const staticSegmentValue = 10;
630
624
  const splatPenalty = -2;
631
625
 
632
626
  const isSplat = s => s === "*";
633
627
 
634
- function computeScore(path) {
628
+ function computeScore(path, index) {
635
629
  let segments = path.split("/");
636
630
  let initialScore = segments.length;
637
631
 
@@ -639,6 +633,10 @@ function computeScore(path) {
639
633
  initialScore += splatPenalty;
640
634
  }
641
635
 
636
+ if (index) {
637
+ initialScore += indexRouteValue;
638
+ }
639
+
642
640
  return segments.filter(s => !isSplat(s)).reduce((score, segment) => score + (paramRe.test(segment) ? dynamicSegmentValue : segment === "" ? emptySegmentValue : staticSegmentValue), initialScore);
643
641
  }
644
642
 
@@ -681,7 +679,11 @@ routesArg, pathname) {
681
679
  pathnameBase: joinPaths([matchedPathname, match.pathnameBase]),
682
680
  route
683
681
  });
684
- matchedPathname = joinPaths([matchedPathname, match.pathnameBase]);
682
+
683
+ if (match.pathnameBase !== "/") {
684
+ matchedPathname = joinPaths([matchedPathname, match.pathnameBase]);
685
+ }
686
+
685
687
  routes = route.children;
686
688
  }
687
689
 
@@ -693,16 +695,17 @@ routesArg, pathname) {
693
695
 
694
696
 
695
697
  function renderMatches(matches) {
698
+ return _renderMatches(matches);
699
+ }
700
+
701
+ function _renderMatches(matches, parentMatches = []) {
696
702
  if (matches == null) return null;
697
- return matches.reduceRight((outlet, match) => {
703
+ return matches.reduceRight((outlet, match, index) => {
698
704
  return /*#__PURE__*/createElement(RouteContext.Provider, {
699
- children: match.route.element || /*#__PURE__*/createElement(Outlet, null),
705
+ children: match.route.element !== undefined ? match.route.element : /*#__PURE__*/createElement(Outlet, null),
700
706
  value: {
701
707
  outlet,
702
- params: match.params,
703
- pathname: match.pathname,
704
- pathnameBase: match.pathnameBase,
705
- route: match.route
708
+ matches: parentMatches.concat(matches.slice(0, index + 1))
706
709
  }
707
710
  });
708
711
  }, null);
@@ -711,11 +714,12 @@ function renderMatches(matches) {
711
714
  * A PathPattern is used to match on some portion of a URL pathname.
712
715
  */
713
716
 
717
+
714
718
  /**
715
719
  * Performs pattern matching on a URL pathname and returns information about
716
720
  * the match.
717
721
  *
718
- * @see https://reactrouter.com/api/matchPath
722
+ * @see https://reactrouter.com/docs/en/v6/api#matchpath
719
723
  */
720
724
  function matchPath(pattern, pathname) {
721
725
  if (typeof pattern === "string") {
@@ -789,7 +793,7 @@ function safelyDecodeURIComponent(value, paramName) {
789
793
  /**
790
794
  * Returns a resolved path object relative to the given pathname.
791
795
  *
792
- * @see https://reactrouter.com/api/resolvePath
796
+ * @see https://reactrouter.com/docs/en/v6/api#resolvepath
793
797
  */
794
798
 
795
799
 
@@ -821,17 +825,48 @@ function resolvePathname(relativePath, fromPathname) {
821
825
  return segments.length > 1 ? segments.join("/") : "/";
822
826
  }
823
827
 
824
- function resolveTo(to, routePathname, locationPathname) {
825
- return resolvePath(to, // If a pathname is explicitly provided in `to`, it should be
826
- // relative to the route context. This is explained in `Note on
827
- // `<Link to>` values` in our migration guide from v5 as a means of
828
- // disambiguation between `to` values that begin with `/` and those
829
- // that do not. However, this is problematic for `to` values that do
830
- // not provide a pathname. `to` can simply be a search or hash
831
- // string, in which case we should assume that the navigation is
832
- // relative to the current location's pathname and *not* the
833
- // route pathname.
834
- getToPathname(to) == null ? locationPathname : routePathname);
828
+ function resolveTo(toArg, routePathnames, locationPathname) {
829
+ let to = typeof toArg === "string" ? parsePath(toArg) : toArg;
830
+ let toPathname = toArg === "" || to.pathname === "" ? "/" : to.pathname; // If a pathname is explicitly provided in `to`, it should be relative to the
831
+ // route context. This is explained in `Note on `<Link to>` values` in our
832
+ // migration guide from v5 as a means of disambiguation between `to` values
833
+ // that begin with `/` and those that do not. However, this is problematic for
834
+ // `to` values that do not provide a pathname. `to` can simply be a search or
835
+ // hash string, in which case we should assume that the navigation is relative
836
+ // to the current location's pathname and *not* the route pathname.
837
+
838
+ let from;
839
+
840
+ if (toPathname == null) {
841
+ from = locationPathname;
842
+ } else {
843
+ let routePathnameIndex = routePathnames.length - 1;
844
+
845
+ if (toPathname.startsWith("..")) {
846
+ let toSegments = toPathname.split("/"); // Each leading .. segment means "go up one route" instead of "go up one
847
+ // URL segment". This is a key difference from how <a href> works and a
848
+ // major reason we call this a "to" value instead of a "href".
849
+
850
+ while (toSegments[0] === "..") {
851
+ toSegments.shift();
852
+ routePathnameIndex -= 1;
853
+ }
854
+
855
+ to.pathname = toSegments.join("/");
856
+ } // If there are more ".." segments than parent routes, resolve relative to
857
+ // the root / URL.
858
+
859
+
860
+ from = routePathnameIndex >= 0 ? routePathnames[routePathnameIndex] : "/";
861
+ }
862
+
863
+ let path = resolvePath(to, from); // Ensure the pathname has a trailing slash if the original to value had one.
864
+
865
+ if (toPathname && toPathname !== "/" && toPathname.endsWith("/") && !path.pathname.endsWith("/")) {
866
+ path.pathname += "/";
867
+ }
868
+
869
+ return path;
835
870
  }
836
871
 
837
872
  function getToPathname(to) {
@@ -864,5 +899,5 @@ const normalizeSearch = search => !search || search === "?" ? "" : search.starts
864
899
 
865
900
  const normalizeHash = hash => !hash || hash === "#" ? "" : hash.startsWith("#") ? hash : "#" + hash; ///////////////////////////////////////////////////////////////////////////////
866
901
 
867
- export { MemoryRouter, Navigate, Outlet, Route, Router, Routes, LocationContext as UNSAFE_LocationContext, NavigationContext as UNSAFE_NavigationContext, RouteContext as UNSAFE_RouteContext, createRoutesFromChildren, generatePath, matchPath, matchRoutes, renderMatches, resolvePath, useBlocker, useHref, useInRouterContext, useLocation, useMatch, useNavigate, useOutlet, useParams, useResolvedPath, useRoutes };
902
+ export { MemoryRouter, Navigate, Outlet, Route, Router, Routes, LocationContext as UNSAFE_LocationContext, NavigationContext as UNSAFE_NavigationContext, RouteContext as UNSAFE_RouteContext, createRoutesFromChildren, generatePath, matchPath, matchRoutes, renderMatches, resolvePath, useHref, useInRouterContext, useLocation, useMatch, useNavigate, useNavigationType, useOutlet, useParams, useResolvedPath, useRoutes };
868
903
  //# sourceMappingURL=react-router.development.js.map