react-router 0.0.0-experimental-e960cf1a → 0.0.0-experimental-a0888892

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.
@@ -107,9 +107,7 @@ export interface RouterProps {
107
107
  navigationType?: NavigationType;
108
108
  navigator: Navigator;
109
109
  static?: boolean;
110
- future?: {
111
- v7_relativeSplatPath?: boolean;
112
- };
110
+ future?: Partial<Pick<FutureConfig, "v7_relativeSplatPath">>;
113
111
  }
114
112
  /**
115
113
  * Provides location context for the rest of the app.
@@ -47,7 +47,7 @@ export interface RouteMatch<ParamKey extends string = string, RouteObjectType ex
47
47
  }
48
48
  export interface DataRouteMatch extends RouteMatch<string, DataRouteObject> {
49
49
  }
50
- export interface DataRouterContextObject extends NavigationContextObject {
50
+ export interface DataRouterContextObject extends Omit<NavigationContextObject, "future"> {
51
51
  router: Router;
52
52
  staticContext?: StaticHandlerContext;
53
53
  }
package/dist/main.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * React Router v0.0.0-experimental-e960cf1a
2
+ * React Router v0.0.0-experimental-a0888892
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * React Router v0.0.0-experimental-e960cf1a
2
+ * React Router v0.0.0-experimental-a0888892
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -323,13 +323,32 @@ function useRoutesImpl(routes, locationArg, dataRouterState, future) {
323
323
  location = locationFromContext;
324
324
  }
325
325
  let pathname = location.pathname || "/";
326
- let remainingPathname = parentPathnameBase === "/" ? pathname : pathname.slice(parentPathnameBase.length) || "/";
326
+ let remainingPathname = pathname;
327
+ if (parentPathnameBase !== "/") {
328
+ // Determine the remaining pathname by removing the # of URL segments the
329
+ // parentPathnameBase has, instead of removing based on character count.
330
+ // This is because we can't guarantee that incoming/outgoing encodings/
331
+ // decodings will match exactly.
332
+ // We decode paths before matching on a per-segment basis with
333
+ // decodeURIComponent(), but we re-encode pathnames via `new URL()` so they
334
+ // match what `window.location.pathname` would reflect. Those don't 100%
335
+ // align when it comes to encoded URI characters such as % and &.
336
+ //
337
+ // So we may end up with:
338
+ // pathname: "/descendant/a%25b/match"
339
+ // parentPathnameBase: "/descendant/a%b"
340
+ //
341
+ // And the direct substring removal approach won't work :/
342
+ let parentSegments = parentPathnameBase.replace(/^\//, "").split("/");
343
+ let segments = pathname.replace(/^\//, "").split("/");
344
+ remainingPathname = "/" + segments.slice(parentSegments.length).join("/");
345
+ }
327
346
  let matches = matchRoutes(routes, {
328
347
  pathname: remainingPathname
329
348
  });
330
349
  {
331
350
  UNSAFE_warning(parentRoute || matches != null, `No routes matched location "${location.pathname}${location.search}${location.hash}" `) ;
332
- 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.`) ;
351
+ UNSAFE_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.`) ;
333
352
  }
334
353
  let renderedMatches = _renderMatches(matches && matches.map(match => Object.assign({}, match, {
335
354
  params: Object.assign({}, parentParams, match.params),
@@ -487,17 +506,24 @@ function _renderMatches(matches, parentMatches = [], dataRouterState = null, fut
487
506
  if (match.route.HydrateFallback || match.route.hydrateFallbackElement) {
488
507
  fallbackIndex = i;
489
508
  }
490
- if (match.route.loader && match.route.id && dataRouterState.loaderData[match.route.id] === undefined && (!dataRouterState.errors || dataRouterState.errors[match.route.id] === undefined)) {
491
- // We found the first route without data/errors which means it's loader
492
- // still needs to run. Flag that we need to render a fallback and
493
- // render up until the appropriate fallback
494
- renderFallback = true;
495
- if (fallbackIndex >= 0) {
496
- renderedMatches = renderedMatches.slice(0, fallbackIndex + 1);
497
- } else {
498
- renderedMatches = [renderedMatches[0]];
509
+ if (match.route.id) {
510
+ let {
511
+ loaderData,
512
+ errors: _errors
513
+ } = dataRouterState;
514
+ let needsToRunLoader = match.route.loader && loaderData[match.route.id] === undefined && (!_errors || _errors[match.route.id] === undefined);
515
+ if (match.route.lazy || needsToRunLoader) {
516
+ // We found the first route that's not ready to render (waiting on
517
+ // lazy, or has a loader that hasn't run yet). Flag that we need to
518
+ // render a fallback and render up until the appropriate fallback
519
+ renderFallback = true;
520
+ if (fallbackIndex >= 0) {
521
+ renderedMatches = renderedMatches.slice(0, fallbackIndex + 1);
522
+ } else {
523
+ renderedMatches = [renderedMatches[0]];
524
+ }
525
+ break;
499
526
  }
500
- break;
501
527
  }
502
528
  }
503
529
  }
@@ -851,7 +877,7 @@ function RouterProvider({
851
877
  // pick up on any render-driven redirects/navigations (useEffect/<Navigate>)
852
878
  React.useLayoutEffect(() => router.subscribe(setState), [router, setState]);
853
879
  React.useEffect(() => {
854
- UNSAFE_warning(fallbackElement == null || !router.future.v7_partialHydration, "`<RouterProvider fallbackElement>` is deprecated when using `v7_partialHydration`") ;
880
+ UNSAFE_warning(fallbackElement == null || !router.future.v7_partialHydration, "`<RouterProvider fallbackElement>` is deprecated when using " + "`v7_partialHydration`, use a `HydrateFallback` component instead") ;
855
881
  // Only log this once on initial mount
856
882
  // eslint-disable-next-line react-hooks/exhaustive-deps
857
883
  }, []);
@@ -876,10 +902,7 @@ function RouterProvider({
876
902
  router,
877
903
  navigator,
878
904
  static: false,
879
- basename,
880
- future: {
881
- v7_relativeSplatPath: router.future.v7_relativeSplatPath
882
- }
905
+ basename
883
906
  }), [router, navigator, basename]);
884
907
  // The fragment and {null} here are important! We need them to keep React 18's
885
908
  // useId happy when we are server-rendering since we may have a <script> here
@@ -895,8 +918,11 @@ function RouterProvider({
895
918
  basename: basename,
896
919
  location: state.location,
897
920
  navigationType: state.historyAction,
898
- navigator: navigator
899
- }, state.initialized ? /*#__PURE__*/React.createElement(DataRoutes, {
921
+ navigator: navigator,
922
+ future: {
923
+ v7_relativeSplatPath: router.future.v7_relativeSplatPath
924
+ }
925
+ }, state.initialized || router.future.v7_partialHydration ? /*#__PURE__*/React.createElement(DataRoutes, {
900
926
  routes: router.routes,
901
927
  future: router.future,
902
928
  state: state