react-router 7.9.3-pre.0 → 7.9.4-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.
Files changed (58) hide show
  1. package/CHANGELOG.md +106 -1
  2. package/dist/development/{chunk-HHJJZWWP.mjs → chunk-5IRCOFJ2.mjs} +8 -4
  3. package/dist/development/{chunk-TZREDCP7.mjs → chunk-I2PHXWY4.mjs} +16 -2
  4. package/dist/development/{chunk-MREZ7GBS.js → chunk-JPM6TDKY.js} +134 -134
  5. package/dist/development/{chunk-OUSD3CXG.js → chunk-V7H6ON6M.js} +28 -14
  6. package/dist/{production/context-BqL5Eckq.d.mts → development/context-DSyS5mLj.d.mts} +1 -1
  7. package/dist/development/dom-export.d.mts +1 -1
  8. package/dist/development/dom-export.js +3 -3
  9. package/dist/development/dom-export.mjs +3 -3
  10. package/dist/{production/index-react-server-client-2EDmGlsZ.d.mts → development/index-react-server-client-BIz4AUNd.d.mts} +2 -2
  11. package/dist/development/{index-react-server-client-DKvU8YRr.d.ts → index-react-server-client-BbRcBjrA.d.ts} +1 -1
  12. package/dist/development/index-react-server-client.d.mts +3 -3
  13. package/dist/development/index-react-server-client.d.ts +2 -2
  14. package/dist/development/index-react-server-client.js +4 -4
  15. package/dist/development/index-react-server-client.mjs +2 -2
  16. package/dist/development/index-react-server.js +1 -1
  17. package/dist/development/index-react-server.mjs +1 -1
  18. package/dist/development/index.d.mts +16 -9
  19. package/dist/development/index.d.ts +14 -7
  20. package/dist/development/index.js +105 -99
  21. package/dist/development/index.mjs +5 -3
  22. package/dist/development/lib/types/internal.d.mts +3 -3
  23. package/dist/development/lib/types/internal.d.ts +2 -2
  24. package/dist/development/lib/types/internal.js +1 -1
  25. package/dist/development/lib/types/internal.mjs +1 -1
  26. package/dist/{production/register-DiOIlEq5.d.mts → development/register-C34pU-in.d.ts} +7 -1
  27. package/dist/development/{register-DiOIlEq5.d.mts → register-CI4bTprK.d.mts} +7 -1
  28. package/dist/development/{route-data-CDwqkzPE.d.mts → route-data-DZQOUSqV.d.mts} +1 -1
  29. package/dist/development/{routeModules-BmVo7q9e.d.ts → routeModules-D5iJ6JYT.d.ts} +1 -1
  30. package/dist/production/{chunk-YE2RU2Y2.js → chunk-A4C524Z4.js} +134 -134
  31. package/dist/production/{chunk-AR4BV4G2.js → chunk-QIDCISSR.js} +28 -14
  32. package/dist/production/{chunk-ZS4K3BVQ.mjs → chunk-TK5RYV7M.mjs} +8 -4
  33. package/dist/production/{chunk-RX77WZIY.mjs → chunk-VDTQF36D.mjs} +16 -2
  34. package/dist/{development/context-BqL5Eckq.d.mts → production/context-DSyS5mLj.d.mts} +1 -1
  35. package/dist/production/dom-export.d.mts +1 -1
  36. package/dist/production/dom-export.js +3 -3
  37. package/dist/production/dom-export.mjs +3 -3
  38. package/dist/{development/index-react-server-client-2EDmGlsZ.d.mts → production/index-react-server-client-BIz4AUNd.d.mts} +2 -2
  39. package/dist/production/{index-react-server-client-DKvU8YRr.d.ts → index-react-server-client-BbRcBjrA.d.ts} +1 -1
  40. package/dist/production/index-react-server-client.d.mts +3 -3
  41. package/dist/production/index-react-server-client.d.ts +2 -2
  42. package/dist/production/index-react-server-client.js +4 -4
  43. package/dist/production/index-react-server-client.mjs +2 -2
  44. package/dist/production/index-react-server.js +1 -1
  45. package/dist/production/index-react-server.mjs +1 -1
  46. package/dist/production/index.d.mts +16 -9
  47. package/dist/production/index.d.ts +14 -7
  48. package/dist/production/index.js +105 -99
  49. package/dist/production/index.mjs +5 -3
  50. package/dist/production/lib/types/internal.d.mts +3 -3
  51. package/dist/production/lib/types/internal.d.ts +2 -2
  52. package/dist/production/lib/types/internal.js +1 -1
  53. package/dist/production/lib/types/internal.mjs +1 -1
  54. package/dist/production/{register-DiOIlEq5.d.ts → register-C34pU-in.d.ts} +7 -1
  55. package/dist/{development/register-DiOIlEq5.d.ts → production/register-CI4bTprK.d.mts} +7 -1
  56. package/dist/production/{route-data-CDwqkzPE.d.mts → route-data-DZQOUSqV.d.mts} +1 -1
  57. package/dist/production/{routeModules-BmVo7q9e.d.ts → routeModules-D5iJ6JYT.d.ts} +1 -1
  58. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,6 +1,111 @@
1
1
  # `react-router`
2
2
 
3
- ## 7.9.3-pre.0
3
+ ## 7.9.4-pre.0
4
+
5
+ ### Patch Changes
6
+
7
+ - handle external redirects in from server actions ([#14400](https://github.com/remix-run/react-router/pull/14400))
8
+ - New (unstable) `useRoute` hook for accessing data from specific routes ([#14407](https://github.com/remix-run/react-router/pull/14407))
9
+
10
+ For example, let's say you have an `admin` route somewhere in your app and you want any child routes of `admin` to all have access to the `loaderData` and `actionData` from `admin.`
11
+
12
+ ```tsx
13
+ // app/routes/admin.tsx
14
+ import { Outlet } from "react-router";
15
+
16
+ export const loader = () => ({ message: "Hello, loader!" });
17
+
18
+ export const action = () => ({ count: 1 });
19
+
20
+ export default function Component() {
21
+ return (
22
+ <div>
23
+ {/* ... */}
24
+ <Outlet />
25
+ {/* ... */}
26
+ </div>
27
+ );
28
+ }
29
+ ```
30
+
31
+ You might even want to create a reusable widget that all of the routes nested under `admin` could use:
32
+
33
+ ```tsx
34
+ import { unstable_useRoute as useRoute } from "react-router";
35
+
36
+ export function AdminWidget() {
37
+ // How to get `message` and `count` from `admin` route?
38
+ }
39
+ ```
40
+
41
+ In framework mode, `useRoute` knows all your app's routes and gives you TS errors when invalid route IDs are passed in:
42
+
43
+ ```tsx
44
+ export function AdminWidget() {
45
+ const admin = useRoute("routes/dmin");
46
+ // ^^^^^^^^^^^
47
+ }
48
+ ```
49
+
50
+ `useRoute` returns `undefined` if the route is not part of the current page:
51
+
52
+ ```tsx
53
+ export function AdminWidget() {
54
+ const admin = useRoute("routes/admin");
55
+ if (!admin) {
56
+ throw new Error(`AdminWidget used outside of "routes/admin"`);
57
+ }
58
+ }
59
+ ```
60
+
61
+ Note: the `root` route is the exception since it is guaranteed to be part of the current page.
62
+ As a result, `useRoute` never returns `undefined` for `root`.
63
+
64
+ `loaderData` and `actionData` are marked as optional since they could be accessed before the `action` is triggered or after the `loader` threw an error:
65
+
66
+ ```tsx
67
+ export function AdminWidget() {
68
+ const admin = useRoute("routes/admin");
69
+ if (!admin) {
70
+ throw new Error(`AdminWidget used outside of "routes/admin"`);
71
+ }
72
+ const { loaderData, actionData } = admin;
73
+ console.log(loaderData);
74
+ // ^? { message: string } | undefined
75
+ console.log(actionData);
76
+ // ^? { count: number } | undefined
77
+ }
78
+ ```
79
+
80
+ If instead of a specific route, you wanted access to the _current_ route's `loaderData` and `actionData`, you can call `useRoute` without arguments:
81
+
82
+ ```tsx
83
+ export function AdminWidget() {
84
+ const currentRoute = useRoute();
85
+ currentRoute.loaderData;
86
+ currentRoute.actionData;
87
+ }
88
+ ```
89
+
90
+ This usage is equivalent to calling `useLoaderData` and `useActionData`, but consolidates all route data access into one hook: `useRoute`.
91
+
92
+ Note: when calling `useRoute()` (without a route ID), TS has no way to know which route is the current route.
93
+ As a result, `loaderData` and `actionData` are typed as `unknown`.
94
+ If you want more type-safety, you can either narrow the type yourself with something like `zod` or you can refactor your app to pass down typed props to your `AdminWidget`:
95
+
96
+ ```tsx
97
+ export function AdminWidget({
98
+ message,
99
+ count,
100
+ }: {
101
+ message: string;
102
+ count: number;
103
+ }) {
104
+ /* ... */
105
+ }
106
+ ```
107
+
108
+ ## 7.9.3
4
109
 
5
110
  ### Patch Changes
6
111
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v7.9.3-pre.0
2
+ * react-router v7.9.4-pre.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -60,7 +60,7 @@ import {
60
60
  withComponentProps,
61
61
  withErrorBoundaryProps,
62
62
  withHydrateFallbackProps
63
- } from "./chunk-TZREDCP7.mjs";
63
+ } from "./chunk-I2PHXWY4.mjs";
64
64
 
65
65
  // lib/dom/ssr/server.tsx
66
66
  import * as React from "react";
@@ -1873,7 +1873,7 @@ function createCallServer({
1873
1873
  globalVar.__reactRouterDataRouter.__setPendingRerender(
1874
1874
  Promise.resolve(payloadPromise).then(async (payload) => {
1875
1875
  if (payload.type === "redirect") {
1876
- if (payload.reload) {
1876
+ if (payload.reload || isExternalLocation(payload.location)) {
1877
1877
  window.location.href = payload.location;
1878
1878
  return () => {
1879
1879
  };
@@ -1890,7 +1890,7 @@ function createCallServer({
1890
1890
  const rerender = await payload.rerender;
1891
1891
  if (rerender && landedActionId < actionId && globalVar.__routerActionID <= actionId) {
1892
1892
  if (rerender.type === "redirect") {
1893
- if (rerender.reload) {
1893
+ if (rerender.reload || isExternalLocation(rerender.location)) {
1894
1894
  window.location.href = rerender.location;
1895
1895
  return;
1896
1896
  }
@@ -2460,6 +2460,10 @@ function debounce(callback, wait) {
2460
2460
  timeoutId = window.setTimeout(() => callback(...args), wait);
2461
2461
  };
2462
2462
  }
2463
+ function isExternalLocation(location2) {
2464
+ const newLocation = new URL(location2, window.location.href);
2465
+ return newLocation.origin !== window.location.origin;
2466
+ }
2463
2467
 
2464
2468
  // lib/rsc/server.ssr.tsx
2465
2469
  import * as React5 from "react";
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v7.9.3-pre.0
2
+ * react-router v7.9.4-pre.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -5552,6 +5552,19 @@ function warningOnce(key, cond, message) {
5552
5552
  warning(false, message);
5553
5553
  }
5554
5554
  }
5555
+ function useRoute(...args) {
5556
+ const currentRouteId = useCurrentRouteId(
5557
+ "useRoute" /* UseRoute */
5558
+ );
5559
+ const id = args[0] ?? currentRouteId;
5560
+ const state = useDataRouterState("useRouteLoaderData" /* UseRouteLoaderData */);
5561
+ const route = state.matches.find(({ route: route2 }) => route2.id === id);
5562
+ if (route === void 0) return void 0;
5563
+ return {
5564
+ loaderData: state.loaderData[id],
5565
+ actionData: state.actionData?.[id]
5566
+ };
5567
+ }
5555
5568
 
5556
5569
  // lib/components.tsx
5557
5570
  import * as React3 from "react";
@@ -9113,7 +9126,7 @@ var isBrowser = typeof window !== "undefined" && typeof window.document !== "und
9113
9126
  try {
9114
9127
  if (isBrowser) {
9115
9128
  window.__reactRouterVersion = // @ts-expect-error
9116
- "7.9.3-pre.0";
9129
+ "7.9.4-pre.0";
9117
9130
  }
9118
9131
  } catch (e) {
9119
9132
  }
@@ -10271,6 +10284,7 @@ export {
10271
10284
  useAsyncValue,
10272
10285
  useAsyncError,
10273
10286
  useBlocker,
10287
+ useRoute,
10274
10288
  warnOnce,
10275
10289
  mapRouteProperties,
10276
10290
  hydrationRouteProperties,