react-router 0.0.0-experimental-7f486334 → 0.0.0-experimental-178bc9ee

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,22 @@
1
1
  # `react-router`
2
2
 
3
+ ## 6.19.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Add `unstable_flushSync` option to `useNavigate`/`useSumbit`/`fetcher.load`/`fetcher.submit` to opt-out of `React.startTransition` and into `ReactDOM.flushSync` for state updates ([#11005](https://github.com/remix-run/react-router/pull/11005))
8
+ - Remove the `unstable_` prefix from the [`useBlocker`](https://reactrouter.com/en/main/hooks/use-blocker) hook as it's been in use for enough time that we are confident in the API. We do not plan to remove the prefix from `unstable_usePrompt` due to differences in how browsers handle `window.confirm` that prevent React Router from guaranteeing consistent/correct behavior. ([#10991](https://github.com/remix-run/react-router/pull/10991))
9
+
10
+ ### Patch Changes
11
+
12
+ - Fix `useActionData` so it returns proper contextual action data and not _any_ action data in the tree ([#11023](https://github.com/remix-run/react-router/pull/11023))
13
+ - Fix bug in `useResolvedPath` that would cause `useResolvedPath(".")` in a splat route to lose the splat portion of the URL path. ([#10983](https://github.com/remix-run/react-router/pull/10983))
14
+
15
+ - ⚠️ This fixes a quite long-standing bug specifically for `"."` paths inside a splat route which incorrectly dropped the splat portion of the URL. If you are relative routing via `"."` inside a splat route in your application you should double check that your logic is not relying on this buggy behavior and update accordingly.
16
+
17
+ - Updated dependencies:
18
+ - `@remix-run/router@1.12.0`
19
+
3
20
  ## 6.18.0
4
21
 
5
22
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { ActionFunction, ActionFunctionArgs, Blocker, BlockerFunction, ErrorResponse, Fetcher, HydrationState, InitialEntry, JsonFunction, LazyRouteFunction, LoaderFunction, LoaderFunctionArgs, Location, Navigation, ParamParseKey, Params, Path, PathMatch, PathPattern, RedirectFunction, RelativeRoutingType, Router as RemixRouter, FutureConfig as RouterFutureConfig, ShouldRevalidateFunction, ShouldRevalidateFunctionArgs, To, UIMatch } from "@remix-run/router";
1
+ import type { ActionFunction, ActionFunctionArgs, Blocker, BlockerFunction, ErrorResponse, Fetcher, HydrationState, InitialEntry, JsonFunction, LazyRouteFunction, LoaderFunction, LoaderFunctionArgs, Location, Navigation, ParamParseKey, Params, Path, PathMatch, PathParam, PathPattern, RedirectFunction, RelativeRoutingType, Router as RemixRouter, FutureConfig as RouterFutureConfig, ShouldRevalidateFunction, ShouldRevalidateFunctionArgs, To, UIMatch } from "@remix-run/router";
2
2
  import { AbortedDeferredError, Action as NavigationType, createPath, defer, generatePath, isRouteErrorResponse, json, matchPath, matchRoutes, parsePath, redirect, redirectDocument, resolvePath } from "@remix-run/router";
3
3
  import type { AwaitProps, FutureConfig, IndexRouteProps, LayoutRouteProps, MemoryRouterProps, NavigateProps, OutletProps, PathRouteProps, RouteProps, RouterProps, RouterProviderProps, RoutesProps } from "./lib/components";
4
4
  import { Await, MemoryRouter, Navigate, Outlet, Route, Router, RouterProvider, Routes, createRoutesFromChildren, renderMatches } from "./lib/components";
@@ -9,7 +9,7 @@ import { useActionData, useAsyncError, useAsyncValue, useBlocker, useHref, useIn
9
9
  type Hash = string;
10
10
  type Pathname = string;
11
11
  type Search = string;
12
- export type { ActionFunction, ActionFunctionArgs, AwaitProps, DataRouteMatch, DataRouteObject, ErrorResponse, Fetcher, FutureConfig, Hash, IndexRouteObject, IndexRouteProps, JsonFunction, LayoutRouteProps, LazyRouteFunction, LoaderFunction, LoaderFunctionArgs, Location, MemoryRouterProps, NavigateFunction, NavigateOptions, NavigateProps, Navigation, Navigator, NonIndexRouteObject, OutletProps, ParamParseKey, Params, Path, PathMatch, PathPattern, PathRouteProps, Pathname, RedirectFunction, RelativeRoutingType, RouteMatch, RouteObject, RouteProps, RouterProps, RouterProviderProps, RoutesProps, Search, ShouldRevalidateFunction, ShouldRevalidateFunctionArgs, To, UIMatch, Blocker as unstable_Blocker, BlockerFunction as unstable_BlockerFunction, };
12
+ export type { ActionFunction, ActionFunctionArgs, AwaitProps, DataRouteMatch, DataRouteObject, ErrorResponse, Fetcher, FutureConfig, Hash, IndexRouteObject, IndexRouteProps, JsonFunction, LayoutRouteProps, LazyRouteFunction, LoaderFunction, LoaderFunctionArgs, Location, MemoryRouterProps, NavigateFunction, NavigateOptions, NavigateProps, Navigation, Navigator, NonIndexRouteObject, OutletProps, ParamParseKey, Params, Path, PathMatch, PathParam, PathPattern, PathRouteProps, Pathname, RedirectFunction, RelativeRoutingType, RouteMatch, RouteObject, RouteProps, RouterProps, RouterProviderProps, RoutesProps, Search, ShouldRevalidateFunction, ShouldRevalidateFunctionArgs, To, UIMatch, Blocker as unstable_Blocker, BlockerFunction as unstable_BlockerFunction, };
13
13
  export { AbortedDeferredError, Await, MemoryRouter, Navigate, NavigationType, Outlet, Route, Router, RouterProvider, Routes, createPath, createRoutesFromChildren, createRoutesFromChildren as createRoutesFromElements, defer, generatePath, isRouteErrorResponse, json, matchPath, matchRoutes, parsePath, redirect, redirectDocument, renderMatches, resolvePath, useBlocker, useActionData, useAsyncError, useAsyncValue, useHref, useInRouterContext, useLoaderData, useLocation, useMatch, useMatches, useNavigate, useNavigation, useNavigationType, useOutlet, useOutletContext, useParams, useResolvedPath, useRevalidator, useRouteError, useRouteLoaderData, useRoutes, };
14
14
  declare function mapRouteProperties(route: RouteObject): Partial<RouteObject> & {
15
15
  hasErrorBoundary: boolean;
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * React Router v0.0.0-experimental-7f486334
2
+ * React Router v0.0.0-experimental-178bc9ee
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -9,7 +9,7 @@
9
9
  * @license MIT
10
10
  */
11
11
  import * as React from 'react';
12
- import { UNSAFE_invariant, joinPaths, matchPath, UNSAFE_getPathContributingMatches, UNSAFE_warning, resolveTo, parsePath, matchRoutes, Action, UNSAFE_convertRouteMatchToUiMatch, stripBasename, IDLE_BLOCKER, isRouteErrorResponse, createMemoryHistory, AbortedDeferredError, createRouter } from '@remix-run/router';
12
+ import { UNSAFE_invariant, joinPaths, matchPath, UNSAFE_getResolveToMatches, UNSAFE_warning, resolveTo, parsePath, matchRoutes, Action, UNSAFE_convertRouteMatchToUiMatch, stripBasename, IDLE_BLOCKER, isRouteErrorResponse, createMemoryHistory, AbortedDeferredError, createRouter } from '@remix-run/router';
13
13
  export { AbortedDeferredError, Action as NavigationType, createPath, defer, generatePath, isRouteErrorResponse, json, matchPath, matchRoutes, parsePath, redirect, redirectDocument, resolvePath } from '@remix-run/router';
14
14
 
15
15
  function _extends() {
@@ -212,7 +212,7 @@ function useNavigateUnstable() {
212
212
  let {
213
213
  pathname: locationPathname
214
214
  } = useLocation();
215
- let routePathnamesJson = JSON.stringify(UNSAFE_getPathContributingMatches(matches).map(match => match.pathnameBase));
215
+ let routePathnamesJson = JSON.stringify(UNSAFE_getResolveToMatches(matches));
216
216
  let activeRef = React.useRef(false);
217
217
  useIsomorphicLayoutEffect(() => {
218
218
  activeRef.current = true;
@@ -301,10 +301,7 @@ function useResolvedPath(to, _temp2) {
301
301
  let {
302
302
  pathname: locationPathname
303
303
  } = useLocation();
304
-
305
- // Use the full pathname for the leaf match so we include splat values
306
- // for "." links
307
- let routePathnamesJson = JSON.stringify(UNSAFE_getPathContributingMatches(matches).map((match, idx) => idx === matches.length - 1 ? match.pathname : match.pathnameBase));
304
+ let routePathnamesJson = JSON.stringify(UNSAFE_getResolveToMatches(matches));
308
305
  return React.useMemo(() => resolveTo(to, JSON.parse(routePathnamesJson), locationPathname, relative === "path"), [to, routePathnamesJson, locationPathname, relative]);
309
306
  }
310
307
 
@@ -321,7 +318,7 @@ function useRoutes(routes, locationArg) {
321
318
  }
322
319
 
323
320
  // Internal implementation with accept optional param for RouterProvider usage
324
- function useRoutesImpl(routes, locationArg, dataRouterState) {
321
+ function useRoutesImpl(routes, locationArg, dataRouterState, future) {
325
322
  !useInRouterContext() ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, // TODO: This error is probably because they somehow have 2 versions of the
326
323
  // router loaded. We can help them understand how to avoid that.
327
324
  "useRoutes() may be used only in the context of a <Router> component.") : UNSAFE_invariant(false) : void 0;
@@ -387,7 +384,7 @@ function useRoutesImpl(routes, locationArg, dataRouterState) {
387
384
  pathnameBase: match.pathnameBase === "/" ? parentPathnameBase : joinPaths([parentPathnameBase,
388
385
  // Re-encode pathnames that were decoded inside matchRoutes
389
386
  navigator.encodeLocation ? navigator.encodeLocation(match.pathnameBase).pathname : match.pathnameBase])
390
- })), parentMatches, dataRouterState);
387
+ })), parentMatches, dataRouterState, future);
391
388
 
392
389
  // When a user passes in a `locationArg`, the associated routes need to
393
390
  // be wrapped in a new `LocationContext.Provider` in order for `useLocation`
@@ -509,7 +506,7 @@ function RenderedRoute(_ref) {
509
506
  value: routeContext
510
507
  }, children);
511
508
  }
512
- function _renderMatches(matches, parentMatches, dataRouterState) {
509
+ function _renderMatches(matches, parentMatches, dataRouterState, future) {
513
510
  var _dataRouterState2;
514
511
  if (parentMatches === void 0) {
515
512
  parentMatches = [];
@@ -517,6 +514,9 @@ function _renderMatches(matches, parentMatches, dataRouterState) {
517
514
  if (dataRouterState === void 0) {
518
515
  dataRouterState = null;
519
516
  }
517
+ if (future === void 0) {
518
+ future = null;
519
+ }
520
520
  if (matches == null) {
521
521
  var _dataRouterState;
522
522
  if ((_dataRouterState = dataRouterState) != null && _dataRouterState.errors) {
@@ -536,18 +536,58 @@ function _renderMatches(matches, parentMatches, dataRouterState) {
536
536
  !(errorIndex >= 0) ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, "Could not find a matching route for errors on route IDs: " + Object.keys(errors).join(",")) : UNSAFE_invariant(false) : void 0;
537
537
  renderedMatches = renderedMatches.slice(0, Math.min(renderedMatches.length, errorIndex + 1));
538
538
  }
539
+
540
+ // If we're in a partial hydration mode, detect if we need to render down to
541
+ // a given Fallback while we load the rest of the hydration data
542
+ let renderFallback = false;
543
+ let fallbackIndex = -1;
544
+ if (dataRouterState && future && future.v7_partialHydration) {
545
+ for (let i = 0; i < renderedMatches.length; i++) {
546
+ let match = renderedMatches[i];
547
+ // Track the deepest fallback up until the first route without data
548
+ if (match.route.Fallback || match.route.fallbackElement) {
549
+ fallbackIndex = i;
550
+ }
551
+ if (match.route.loader && match.route.id && dataRouterState.loaderData[match.route.id] === undefined) {
552
+ // We found the first route without data, flag that we need to render
553
+ // a fallback and render up until the appropriate fallback
554
+ renderFallback = true;
555
+ if (fallbackIndex >= 0) {
556
+ renderedMatches = renderedMatches.slice(0, fallbackIndex + 1);
557
+ } else {
558
+ renderedMatches = [renderedMatches[0]];
559
+ }
560
+ break;
561
+ }
562
+ }
563
+ }
539
564
  return renderedMatches.reduceRight((outlet, match, index) => {
540
- let error = match.route.id ? errors == null ? void 0 : errors[match.route.id] : null;
541
- // Only data routers handle errors
565
+ // Only data routers handle errors/fallbacks
566
+ let error;
567
+ let fallback = false;
542
568
  let errorElement = null;
569
+ let fallbackElement = null;
543
570
  if (dataRouterState) {
571
+ error = errors && match.route.id ? errors[match.route.id] : null;
544
572
  errorElement = match.route.errorElement || defaultErrorElement;
573
+ if (renderFallback) {
574
+ if (fallbackIndex < 0 && index === 0) {
575
+ warningOnce("route-fallback", false, "No `Fallback` element provided to render during initial hydration");
576
+ fallback = true;
577
+ fallbackElement = null;
578
+ } else if (fallbackIndex === index) {
579
+ fallback = true;
580
+ fallbackElement = match.route.fallbackElement || null;
581
+ }
582
+ }
545
583
  }
546
584
  let matches = parentMatches.concat(renderedMatches.slice(0, index + 1));
547
585
  let getChildren = () => {
548
586
  let children;
549
587
  if (error) {
550
588
  children = errorElement;
589
+ } else if (fallback) {
590
+ children = fallbackElement;
551
591
  } else if (match.route.Component) {
552
592
  // Note: This is a de-optimized path since React won't re-use the
553
593
  // ReactElement since it's identity changes with each new
@@ -701,9 +741,8 @@ function useRouteLoaderData(routeId) {
701
741
  */
702
742
  function useActionData() {
703
743
  let state = useDataRouterState(DataRouterStateHook.UseActionData);
704
- let route = React.useContext(RouteContext);
705
- !route ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, "useActionData must be used inside a RouteContext") : UNSAFE_invariant(false) : void 0;
706
- return Object.values((state == null ? void 0 : state.actionData) || {})[0];
744
+ let routeId = useCurrentRouteId(DataRouterStateHook.UseLoaderData);
745
+ return state.actionData ? state.actionData[routeId] : undefined;
707
746
  }
708
747
 
709
748
  /**
@@ -895,6 +934,11 @@ function RouterProvider(_ref) {
895
934
  // Need to use a layout effect here so we are subscribed early enough to
896
935
  // pick up on any render-driven redirects/navigations (useEffect/<Navigate>)
897
936
  React.useLayoutEffect(() => router.subscribe(setState), [router, setState]);
937
+ React.useEffect(() => {
938
+ process.env.NODE_ENV !== "production" ? UNSAFE_warning(fallbackElement == null || !router.future.v7_partialHydration, "`<RouterProvider fallbackElement>` is deprecated when using `v7_partialHydration`") : void 0;
939
+ // Only log this once on initial mount
940
+ // eslint-disable-next-line react-hooks/exhaustive-deps
941
+ }, []);
898
942
  let navigator = React.useMemo(() => {
899
943
  return {
900
944
  createHref: router.createHref,
@@ -936,15 +980,17 @@ function RouterProvider(_ref) {
936
980
  navigator: navigator
937
981
  }, state.initialized ? /*#__PURE__*/React.createElement(DataRoutes, {
938
982
  routes: router.routes,
983
+ future: router.future,
939
984
  state: state
940
985
  }) : fallbackElement))), null);
941
986
  }
942
987
  function DataRoutes(_ref2) {
943
988
  let {
944
989
  routes,
990
+ future,
945
991
  state
946
992
  } = _ref2;
947
- return useRoutesImpl(routes, undefined, state);
993
+ return useRoutesImpl(routes, undefined, state, future);
948
994
  }
949
995
  /**
950
996
  * A `<Router>` that stores all entries in memory.
@@ -1017,7 +1063,7 @@ function Navigate(_ref4) {
1017
1063
 
1018
1064
  // Resolve the path outside of the effect so that when effects run twice in
1019
1065
  // StrictMode they navigate to the same place
1020
- let path = resolveTo(to, UNSAFE_getPathContributingMatches(matches).map(match => match.pathnameBase), locationPathname, relative === "path");
1066
+ let path = resolveTo(to, UNSAFE_getResolveToMatches(matches), locationPathname, relative === "path");
1021
1067
  let jsonPath = JSON.stringify(path);
1022
1068
  React.useEffect(() => navigate(JSON.parse(jsonPath), {
1023
1069
  replace,
@@ -1321,6 +1367,17 @@ function mapRouteProperties(route) {
1321
1367
  Component: undefined
1322
1368
  });
1323
1369
  }
1370
+ if (route.Fallback) {
1371
+ if (process.env.NODE_ENV !== "production") {
1372
+ if (route.fallbackElement) {
1373
+ process.env.NODE_ENV !== "production" ? UNSAFE_warning(false, "You should not include both `Fallback` and `fallbackElement` on your route - " + "`Fallback` will be used.") : void 0;
1374
+ }
1375
+ }
1376
+ Object.assign(updates, {
1377
+ fallbackElement: /*#__PURE__*/React.createElement(route.Fallback),
1378
+ Fallback: undefined
1379
+ });
1380
+ }
1324
1381
  if (route.ErrorBoundary) {
1325
1382
  if (process.env.NODE_ENV !== "production") {
1326
1383
  if (route.errorElement) {