@react-router/dev 7.9.3 → 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.
- package/CHANGELOG.md +110 -8
- package/dist/cli/index.js +25 -2
- package/dist/config.js +1 -1
- package/dist/routes.js +1 -1
- package/dist/vite/cloudflare.js +1 -1
- package/dist/vite.js +25 -2
- package/package.json +7 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,115 @@
|
|
|
1
1
|
# `@react-router/dev`
|
|
2
2
|
|
|
3
|
+
## 7.9.4-pre.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Update `valibot` dependency to `^1.1.0` ([#14379](https://github.com/remix-run/react-router/pull/14379))
|
|
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
|
+
- Updated dependencies:
|
|
109
|
+
- `react-router@7.9.4-pre.0`
|
|
110
|
+
- `@react-router/node@7.9.4-pre.0`
|
|
111
|
+
- `@react-router/serve@7.9.4-pre.0`
|
|
112
|
+
|
|
3
113
|
## 7.9.3
|
|
4
114
|
|
|
5
115
|
### Patch Changes
|
|
@@ -45,7 +155,6 @@
|
|
|
45
155
|
- Stabilize middleware and context APIs. ([#14215](https://github.com/remix-run/react-router/pull/14215))
|
|
46
156
|
|
|
47
157
|
We have removed the `unstable_` prefix from the following APIs and they are now considered stable and ready for production use:
|
|
48
|
-
|
|
49
158
|
- [`RouterContextProvider`](https://reactrouter.com/api/utils/RouterContextProvider)
|
|
50
159
|
- [`createContext`](https://reactrouter.com/api/utils/createContext)
|
|
51
160
|
- `createBrowserRouter` [`getContext`](https://reactrouter.com/api/data-routers/createBrowserRouter#optsgetcontext) option
|
|
@@ -788,7 +897,6 @@
|
|
|
788
897
|
```
|
|
789
898
|
|
|
790
899
|
This initial implementation targets type inference for:
|
|
791
|
-
|
|
792
900
|
- `Params` : Path parameters from your routing config in `routes.ts` including file-based routing
|
|
793
901
|
- `LoaderData` : Loader data from `loader` and/or `clientLoader` within your route module
|
|
794
902
|
- `ActionData` : Action data from `action` and/or `clientAction` within your route module
|
|
@@ -803,7 +911,6 @@
|
|
|
803
911
|
```
|
|
804
912
|
|
|
805
913
|
Check out our docs for more:
|
|
806
|
-
|
|
807
914
|
- [_Explanations > Type Safety_](https://reactrouter.com/dev/guides/explanation/type-safety)
|
|
808
915
|
- [_How-To > Setting up type safety_](https://reactrouter.com/dev/guides/how-to/setting-up-type-safety)
|
|
809
916
|
|
|
@@ -1003,7 +1110,6 @@
|
|
|
1003
1110
|
- Vite: Provide `Unstable_ServerBundlesFunction` and `Unstable_VitePluginConfig` types ([#8654](https://github.com/remix-run/remix/pull/8654))
|
|
1004
1111
|
|
|
1005
1112
|
- Vite: add `--sourcemapClient` and `--sourcemapServer` flags to `remix vite:build` ([#8613](https://github.com/remix-run/remix/pull/8613))
|
|
1006
|
-
|
|
1007
1113
|
- `--sourcemapClient`
|
|
1008
1114
|
|
|
1009
1115
|
- `--sourcemapClient=inline`
|
|
@@ -1340,7 +1446,6 @@
|
|
|
1340
1446
|
- Add support for `clientLoader`/`clientAction`/`HydrateFallback` route exports ([RFC](https://github.com/remix-run/remix/discussions/7634)) ([#8173](https://github.com/remix-run/remix/pull/8173))
|
|
1341
1447
|
|
|
1342
1448
|
Remix now supports loaders/actions that run on the client (in addition to, or instead of the loader/action that runs on the server). While we still recommend server loaders/actions for the majority of your data needs in a Remix app - these provide some levers you can pull for more advanced use-cases such as:
|
|
1343
|
-
|
|
1344
1449
|
- Leveraging a data source local to the browser (i.e., `localStorage`)
|
|
1345
1450
|
- Managing a client-side cache of server data (like `IndexedDB`)
|
|
1346
1451
|
- Bypassing the Remix server in a BFF setup and hitting your API directly from the browser
|
|
@@ -1744,7 +1849,6 @@
|
|
|
1744
1849
|
- Output esbuild metafiles for bundle analysis ([#6772](https://github.com/remix-run/remix/pull/6772))
|
|
1745
1850
|
|
|
1746
1851
|
Written to server build directory (`build/` by default):
|
|
1747
|
-
|
|
1748
1852
|
- `metafile.css.json`
|
|
1749
1853
|
- `metafile.js.json` (browser JS)
|
|
1750
1854
|
- `metafile.server.json` (server JS)
|
|
@@ -1842,7 +1946,6 @@
|
|
|
1842
1946
|
- built-in tls support ([#6483](https://github.com/remix-run/remix/pull/6483))
|
|
1843
1947
|
|
|
1844
1948
|
New options:
|
|
1845
|
-
|
|
1846
1949
|
- `--tls-key` / `tlsKey`: TLS key
|
|
1847
1950
|
- `--tls-cert` / `tlsCert`: TLS Certificate
|
|
1848
1951
|
|
|
@@ -2113,7 +2216,6 @@
|
|
|
2113
2216
|
```
|
|
2114
2217
|
|
|
2115
2218
|
The dev server will:
|
|
2116
|
-
|
|
2117
2219
|
- force `NODE_ENV=development` and warn you if it was previously set to something else
|
|
2118
2220
|
- rebuild your app whenever your Remix app code changes
|
|
2119
2221
|
- restart your app server whenever rebuilds succeed
|
package/dist/cli/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* @react-router/dev v7.9.
|
|
3
|
+
* @react-router/dev v7.9.4-pre.0
|
|
4
4
|
*
|
|
5
5
|
* Copyright (c) Remix Software Inc.
|
|
6
6
|
*
|
|
@@ -980,9 +980,10 @@ function generateRoutes(ctx) {
|
|
|
980
980
|
interface Register {
|
|
981
981
|
pages: Pages
|
|
982
982
|
routeFiles: RouteFiles
|
|
983
|
+
routeModules: RouteModules
|
|
983
984
|
}
|
|
984
985
|
}
|
|
985
|
-
` + "\n\n" + generate(pagesType(allPages)).code + "\n\n" + generate(routeFilesType({ fileToRoutes, routeToPages })).code
|
|
986
|
+
` + "\n\n" + generate(pagesType(allPages)).code + "\n\n" + generate(routeFilesType({ fileToRoutes, routeToPages })).code + "\n\n" + generate(routeModulesType(ctx)).code
|
|
986
987
|
};
|
|
987
988
|
const allAnnotations = Array.from(fileToRoutes.entries()).filter(([file]) => isInAppDirectory(ctx, file)).map(
|
|
988
989
|
([file, routeIds]) => getRouteAnnotations({ ctx, file, routeIds, lineages })
|
|
@@ -1051,6 +1052,28 @@ function routeFilesType({
|
|
|
1051
1052
|
)
|
|
1052
1053
|
);
|
|
1053
1054
|
}
|
|
1055
|
+
function routeModulesType(ctx) {
|
|
1056
|
+
return t2.tsTypeAliasDeclaration(
|
|
1057
|
+
t2.identifier("RouteModules"),
|
|
1058
|
+
null,
|
|
1059
|
+
t2.tsTypeLiteral(
|
|
1060
|
+
Object.values(ctx.config.routes).map(
|
|
1061
|
+
(route) => t2.tsPropertySignature(
|
|
1062
|
+
t2.stringLiteral(route.id),
|
|
1063
|
+
t2.tsTypeAnnotation(
|
|
1064
|
+
t2.tsTypeQuery(
|
|
1065
|
+
t2.tsImportType(
|
|
1066
|
+
t2.stringLiteral(
|
|
1067
|
+
`./${Path3.relative(ctx.rootDirectory, ctx.config.appDirectory)}/${route.file}`
|
|
1068
|
+
)
|
|
1069
|
+
)
|
|
1070
|
+
)
|
|
1071
|
+
)
|
|
1072
|
+
)
|
|
1073
|
+
)
|
|
1074
|
+
)
|
|
1075
|
+
);
|
|
1076
|
+
}
|
|
1054
1077
|
function isInAppDirectory(ctx, routeFile) {
|
|
1055
1078
|
const path9 = Path3.resolve(ctx.config.appDirectory, routeFile);
|
|
1056
1079
|
return path9.startsWith(ctx.config.appDirectory);
|
package/dist/config.js
CHANGED
package/dist/routes.js
CHANGED
package/dist/vite/cloudflare.js
CHANGED
package/dist/vite.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @react-router/dev v7.9.
|
|
2
|
+
* @react-router/dev v7.9.4-pre.0
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -968,9 +968,10 @@ function generateRoutes(ctx) {
|
|
|
968
968
|
interface Register {
|
|
969
969
|
pages: Pages
|
|
970
970
|
routeFiles: RouteFiles
|
|
971
|
+
routeModules: RouteModules
|
|
971
972
|
}
|
|
972
973
|
}
|
|
973
|
-
` + "\n\n" + generate(pagesType(allPages)).code + "\n\n" + generate(routeFilesType({ fileToRoutes, routeToPages })).code
|
|
974
|
+
` + "\n\n" + generate(pagesType(allPages)).code + "\n\n" + generate(routeFilesType({ fileToRoutes, routeToPages })).code + "\n\n" + generate(routeModulesType(ctx)).code
|
|
974
975
|
};
|
|
975
976
|
const allAnnotations = Array.from(fileToRoutes.entries()).filter(([file]) => isInAppDirectory(ctx, file)).map(
|
|
976
977
|
([file, routeIds]) => getRouteAnnotations({ ctx, file, routeIds, lineages })
|
|
@@ -1039,6 +1040,28 @@ function routeFilesType({
|
|
|
1039
1040
|
)
|
|
1040
1041
|
);
|
|
1041
1042
|
}
|
|
1043
|
+
function routeModulesType(ctx) {
|
|
1044
|
+
return t2.tsTypeAliasDeclaration(
|
|
1045
|
+
t2.identifier("RouteModules"),
|
|
1046
|
+
null,
|
|
1047
|
+
t2.tsTypeLiteral(
|
|
1048
|
+
Object.values(ctx.config.routes).map(
|
|
1049
|
+
(route) => t2.tsPropertySignature(
|
|
1050
|
+
t2.stringLiteral(route.id),
|
|
1051
|
+
t2.tsTypeAnnotation(
|
|
1052
|
+
t2.tsTypeQuery(
|
|
1053
|
+
t2.tsImportType(
|
|
1054
|
+
t2.stringLiteral(
|
|
1055
|
+
`./${Path3.relative(ctx.rootDirectory, ctx.config.appDirectory)}/${route.file}`
|
|
1056
|
+
)
|
|
1057
|
+
)
|
|
1058
|
+
)
|
|
1059
|
+
)
|
|
1060
|
+
)
|
|
1061
|
+
)
|
|
1062
|
+
)
|
|
1063
|
+
);
|
|
1064
|
+
}
|
|
1042
1065
|
function isInAppDirectory(ctx, routeFile) {
|
|
1043
1066
|
const path9 = Path3.resolve(ctx.config.appDirectory, routeFile);
|
|
1044
1067
|
return path9.startsWith(ctx.config.appDirectory);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-router/dev",
|
|
3
|
-
"version": "7.9.
|
|
3
|
+
"version": "7.9.4-pre.0",
|
|
4
4
|
"description": "Dev tools and CLI for React Router",
|
|
5
5
|
"homepage": "https://reactrouter.com",
|
|
6
6
|
"bugs": {
|
|
@@ -84,9 +84,9 @@
|
|
|
84
84
|
"react-refresh": "^0.14.0",
|
|
85
85
|
"semver": "^7.3.7",
|
|
86
86
|
"tinyglobby": "^0.2.14",
|
|
87
|
-
"valibot": "^
|
|
87
|
+
"valibot": "^1.1.0",
|
|
88
88
|
"vite-node": "^3.2.2",
|
|
89
|
-
"@react-router/node": "7.9.
|
|
89
|
+
"@react-router/node": "7.9.4-pre.0"
|
|
90
90
|
},
|
|
91
91
|
"devDependencies": {
|
|
92
92
|
"@types/babel__core": "^7.20.5",
|
|
@@ -109,16 +109,16 @@
|
|
|
109
109
|
"vite": "^6.1.0",
|
|
110
110
|
"wireit": "0.14.9",
|
|
111
111
|
"wrangler": "^4.23.0",
|
|
112
|
-
"@react-router/serve": "7.9.
|
|
113
|
-
"react-router": "^7.9.
|
|
112
|
+
"@react-router/serve": "7.9.4-pre.0",
|
|
113
|
+
"react-router": "^7.9.4-pre.0"
|
|
114
114
|
},
|
|
115
115
|
"peerDependencies": {
|
|
116
116
|
"@vitejs/plugin-rsc": "*",
|
|
117
117
|
"typescript": "^5.1.0",
|
|
118
118
|
"vite": "^5.1.0 || ^6.0.0 || ^7.0.0",
|
|
119
119
|
"wrangler": "^3.28.2 || ^4.0.0",
|
|
120
|
-
"@react-router/serve": "^7.9.
|
|
121
|
-
"react-router": "^7.9.
|
|
120
|
+
"@react-router/serve": "^7.9.4-pre.0",
|
|
121
|
+
"react-router": "^7.9.4-pre.0"
|
|
122
122
|
},
|
|
123
123
|
"peerDependenciesMeta": {
|
|
124
124
|
"@vitejs/plugin-rsc": {
|