react-router 7.2.0 → 7.3.0-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 (40) hide show
  1. package/CHANGELOG.md +259 -0
  2. package/dist/development/{chunk-HA7DTUK3.mjs → chunk-W5LWFPOT.mjs} +851 -336
  3. package/dist/development/dom-export.d.mts +13 -3
  4. package/dist/development/dom-export.d.ts +13 -3
  5. package/dist/development/dom-export.js +371 -79
  6. package/dist/development/dom-export.mjs +14 -5
  7. package/dist/development/{fog-of-war-Cm1iXIp7.d.ts → fog-of-war-CvttGpNz.d.ts} +93 -9
  8. package/dist/{production/fog-of-war-Cm1iXIp7.d.ts → development/fog-of-war-Da8gpnoZ.d.mts} +93 -9
  9. package/dist/{production/data-CQbyyGzl.d.mts → development/future-ldDp5FKH.d.mts} +11 -1
  10. package/dist/development/{data-CQbyyGzl.d.mts → future-ldDp5FKH.d.ts} +11 -1
  11. package/dist/development/index.d.mts +16 -14
  12. package/dist/development/index.d.ts +16 -14
  13. package/dist/development/index.js +853 -336
  14. package/dist/development/index.mjs +6 -2
  15. package/dist/development/lib/types/route-module.d.mts +24 -6
  16. package/dist/development/lib/types/route-module.d.ts +24 -6
  17. package/dist/development/lib/types/route-module.js +1 -1
  18. package/dist/development/lib/types/route-module.mjs +1 -1
  19. package/dist/{production/route-data-BmvbmBej.d.mts → development/route-data-H2S3hwhf.d.mts} +66 -13
  20. package/dist/development/{route-data-BmvbmBej.d.mts → route-data-H2S3hwhf.d.ts} +66 -13
  21. package/dist/production/{chunk-Z4EF7MSU.mjs → chunk-ZITGHOQF.mjs} +851 -336
  22. package/dist/production/dom-export.d.mts +13 -3
  23. package/dist/production/dom-export.d.ts +13 -3
  24. package/dist/production/dom-export.js +371 -79
  25. package/dist/production/dom-export.mjs +14 -5
  26. package/dist/production/{fog-of-war-BALYJxf_.d.mts → fog-of-war-CvttGpNz.d.ts} +93 -9
  27. package/dist/{development/fog-of-war-BALYJxf_.d.mts → production/fog-of-war-Da8gpnoZ.d.mts} +93 -9
  28. package/dist/{development/data-CQbyyGzl.d.ts → production/future-ldDp5FKH.d.mts} +11 -1
  29. package/dist/production/{data-CQbyyGzl.d.ts → future-ldDp5FKH.d.ts} +11 -1
  30. package/dist/production/index.d.mts +16 -14
  31. package/dist/production/index.d.ts +16 -14
  32. package/dist/production/index.js +853 -336
  33. package/dist/production/index.mjs +6 -2
  34. package/dist/production/lib/types/route-module.d.mts +24 -6
  35. package/dist/production/lib/types/route-module.d.ts +24 -6
  36. package/dist/production/lib/types/route-module.js +1 -1
  37. package/dist/production/lib/types/route-module.mjs +1 -1
  38. package/dist/{development/route-data-BmvbmBej.d.ts → production/route-data-H2S3hwhf.d.mts} +66 -13
  39. package/dist/production/{route-data-BmvbmBej.d.ts → route-data-H2S3hwhf.d.ts} +66 -13
  40. package/package.json +3 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,264 @@
1
1
  # `react-router`
2
2
 
3
+ ## 7.3.0-pre.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Add `fetcherKey` as a parameter to `patchRoutesOnNavigation` ([#13061](https://github.com/remix-run/react-router/pull/13061))
8
+
9
+ - In framework mode, Lazy Route Discovery will now detect manifest version mismatches after a new deploy
10
+ - On navigations to undiscovered routes, this mismatch will trigger a document reload of the destination path
11
+ - On `fetcher` calls to undiscovered routes, this mismatch will trigger a document reload of the current path
12
+
13
+ ### Patch Changes
14
+
15
+ - Skip resource route flow in dev server in SPA mode ([#13113](https://github.com/remix-run/react-router/pull/13113))
16
+ - Support middleware on routes (unstable) ([#12941](https://github.com/remix-run/react-router/pull/12941))
17
+
18
+ Middleware is implemented behind a `future.unstable_middleware` flag. To enable, you must enable the flag and the types in your `react-router-config.ts` file:
19
+
20
+ ```ts
21
+ import type { Config } from "@react-router/dev/config";
22
+ import type { Future } from "react-router";
23
+
24
+ declare module "react-router" {
25
+ interface Future {
26
+ unstable_middleware: true; // 👈 Enable middleware types
27
+ }
28
+ }
29
+
30
+ export default {
31
+ future: {
32
+ unstable_middleware: true, // 👈 Enable middleware
33
+ },
34
+ } satisfies Config;
35
+ ```
36
+
37
+ ⚠️ Middleware is unstable and should not be adopted in production. There is at least one known de-optimization in route module loading for `clientMiddleware` that we will be addressing this before a stable release.
38
+
39
+ ⚠️ Enabling middleware contains a breaking change to the `context` parameter passed to your `loader`/`action` functions - see below for more information.
40
+
41
+ Once enabled, routes can define an array of middleware functions that will run sequentially before route handlers run. These functions accept the same parameters as `loader`/`action` plus an additional `next` parameter to run the remaining data pipeline. This allows middlewares to perform logic before and after handlers execute.
42
+
43
+ ```tsx
44
+ // Framework mode
45
+ export const unstable_middleware = [serverLogger, serverAuth]; // server
46
+ export const unstable_clientMiddleware = [clientLogger]; // client
47
+
48
+ // Library mode
49
+ const routes = [
50
+ {
51
+ path: "/",
52
+ // Middlewares are client-side for library mode SPA's
53
+ unstable_middleware: [clientLogger, clientAuth],
54
+ loader: rootLoader,
55
+ Component: Root,
56
+ },
57
+ ];
58
+ ```
59
+
60
+ Here's a simple example of a client-side logging middleware that can be placed on the root route:
61
+
62
+ ```tsx
63
+ const clientLogger: Route.unstable_ClientMiddlewareFunction = async (
64
+ { request },
65
+ next
66
+ ) => {
67
+ let start = performance.now();
68
+
69
+ // Run the remaining middlewares and all route loaders
70
+ await next();
71
+
72
+ let duration = performance.now() - start;
73
+ console.log(`Navigated to ${request.url} (${duration}ms)`);
74
+ };
75
+ ```
76
+
77
+ Note that in the above example, the `next`/`middleware` functions don't return anything. This is by design as on the client there is no "response" to send over the network like there would be for middlewares running on the server. The data is all handled behind the scenes by the stateful `router`.
78
+
79
+ For a server-side middleware, the `next` function will return the HTTP `Response` that React Router will be sending across the wire, thus giving you a chance to make changes as needed. You may throw a new response to short circuit and respond immediately, or you may return a new or altered response to override the default returned by `next()`.
80
+
81
+ ```tsx
82
+ const serverLogger: Route.unstable_MiddlewareFunction = async (
83
+ { request, params, context },
84
+ next
85
+ ) => {
86
+ let start = performance.now();
87
+
88
+ // 👇 Grab the response here
89
+ let res = await next();
90
+
91
+ let duration = performance.now() - start;
92
+ console.log(`Navigated to ${request.url} (${duration}ms)`);
93
+
94
+ // 👇 And return it here (optional if you don't modify the response)
95
+ return res;
96
+ };
97
+ ```
98
+
99
+ You can throw a `redirect` from a middleware to short circuit any remaining processing:
100
+
101
+ ```tsx
102
+ import { sessionContext } from "../context";
103
+ const serverAuth: Route.unstable_MiddlewareFunction = (
104
+ { request, params, context },
105
+ next
106
+ ) => {
107
+ let session = context.get(sessionContext);
108
+ let user = session.get("user");
109
+ if (!user) {
110
+ session.set("returnTo", request.url);
111
+ throw redirect("/login", 302);
112
+ }
113
+ };
114
+ ```
115
+
116
+ _Note that in cases like this where you don't need to do any post-processing you don't need to call the `next` function or return a `Response`._
117
+
118
+ Here's another example of using a server middleware to detect 404s and check the CMS for a redirect:
119
+
120
+ ```tsx
121
+ const redirects: Route.unstable_MiddlewareFunction = async ({
122
+ request,
123
+ next,
124
+ }) => {
125
+ // attempt to handle the request
126
+ let res = await next();
127
+
128
+ // if it's a 404, check the CMS for a redirect, do it last
129
+ // because it's expensive
130
+ if (res.status === 404) {
131
+ let cmsRedirect = await checkCMSRedirects(request.url);
132
+ if (cmsRedirect) {
133
+ throw redirect(cmsRedirect, 302);
134
+ }
135
+ }
136
+
137
+ return res;
138
+ };
139
+ ```
140
+
141
+ **`context` parameter**
142
+
143
+ When middleware is enabled, your application will use a different type of `context` parameter in your loaders and actions to provide better type safety. Instead of `AppLoadContext`, `context` will now be an instance of `ContextProvider` that you can use with type-safe contexts (similar to `React.createContext`):
144
+
145
+ ```ts
146
+ import { unstable_createContext } from "react-router";
147
+ import { Route } from "./+types/root";
148
+ import type { Session } from "./sessions.server";
149
+ import { getSession } from "./sessions.server";
150
+
151
+ let sessionContext = unstable_createContext<Session>();
152
+
153
+ const sessionMiddleware: Route.unstable_MiddlewareFunction = ({
154
+ context,
155
+ request,
156
+ }) => {
157
+ let session = await getSession(request);
158
+ context.set(sessionContext, session);
159
+ // ^ must be of type Session
160
+ };
161
+
162
+ // ... then in some downstream middleware
163
+ const loggerMiddleware: Route.unstable_MiddlewareFunction = ({
164
+ context,
165
+ request,
166
+ }) => {
167
+ let session = context.get(sessionContext);
168
+ // ^ typeof Session
169
+ console.log(session.get("userId"), request.method, request.url);
170
+ };
171
+
172
+ // ... or some downstream loader
173
+ export function loader({ context }: Route.LoaderArgs) {
174
+ let session = context.get(sessionContext);
175
+ let profile = await getProfile(session.get("userId"));
176
+ return { profile };
177
+ }
178
+ ```
179
+
180
+ If you are using a custom server with a `getLoadContext` function, the return value for initial context values passed from the server adapter layer is no longer an object and should now return an `unstable_InitialContext` (`Map<RouterContext, unknown>`):
181
+
182
+ ```ts
183
+ let adapterContext = unstable_createContext<MyAdapterContext>();
184
+
185
+ function getLoadContext(req, res): unstable_InitialContext {
186
+ let map = new Map();
187
+ map.set(adapterContext, getAdapterContext(req));
188
+ return map;
189
+ }
190
+ ```
191
+
192
+ - Fix types for loaderData and actionData that contained `Record`s ([#13139](https://github.com/remix-run/react-router/pull/13139))
193
+
194
+ UNSTABLE(BREAKING):
195
+
196
+ `unstable_SerializesTo` added a way to register custom serialization types in Single Fetch for other library and framework authors like Apollo.
197
+ It was implemented with branded type whose branded property that was made optional so that casting arbitrary values was easy:
198
+
199
+ ```ts
200
+ // without the brand being marked as optional
201
+ let x1 = 42 as unknown as unstable_SerializesTo<number>;
202
+ // ^^^^^^^^^^
203
+
204
+ // with the brand being marked as optional
205
+ let x2 = 42 as unstable_SerializesTo<number>;
206
+ ```
207
+
208
+ However, this broke type inference in `loaderData` and `actionData` for any `Record` types as those would now (incorrectly) match `unstable_SerializesTo`.
209
+ This affected all users, not just those that depended on `unstable_SerializesTo`.
210
+ To fix this, the branded property of `unstable_SerializesTo` is marked as required instead of optional.
211
+
212
+ For library and framework authors using `unstable_SerializesTo`, you may need to add `as unknown` casts before casting to `unstable_SerializesTo`.
213
+
214
+ - Fix single fetch `_root.data` requests when a `basename` is used ([#12898](https://github.com/remix-run/react-router/pull/12898))
215
+ - Add `context` support to client side data routers (unstable) ([#12941](https://github.com/remix-run/react-router/pull/12941))
216
+
217
+ Your application `loader` and `action` functions on the client will now receive a `context` parameter. This is an instance of `unstable_RouterContextProvider` that you use with type-safe contexts (similar to `React.createContext`) and is most useful with the corresponding `middleware`/`clientMiddleware` API's:
218
+
219
+ ```ts
220
+ import { unstable_createContext } from "react-router";
221
+
222
+ type User = {
223
+ /*...*/
224
+ };
225
+
226
+ let userContext = unstable_createContext<User>();
227
+
228
+ function sessionMiddleware({ context }) {
229
+ let user = await getUser();
230
+ context.set(userContext, user);
231
+ }
232
+
233
+ // ... then in some downstream loader
234
+ function loader({ context }) {
235
+ let user = context.get(userContext);
236
+ let profile = await getProfile(user.id);
237
+ return { profile };
238
+ }
239
+ ```
240
+
241
+ Similar to server-side requests, a fresh `context` will be created per navigation (or `fetcher` call). If you have initial data you'd like to populate in the context for every request, you can provide an `unstable_getContext` function at the root of your app:
242
+
243
+ - Library mode - `createBrowserRouter(routes, { unstable_getContext })`
244
+ - Framework mode - `<HydratedRouter unstable_getContext>`
245
+
246
+ This function should return an value of type `unstable_InitialContext` which is a `Map<unstable_RouterContext, unknown>` of context's and initial values:
247
+
248
+ ```ts
249
+ const loggerContext = unstable_createContext<(...args: unknown[]) => void>();
250
+
251
+ function logger(...args: unknown[]) {
252
+ console.log(new Date.toISOString(), ...args);
253
+ }
254
+
255
+ function unstable_getContext() {
256
+ let map = new Map();
257
+ map.set(loggerContext, logger);
258
+ return map;
259
+ }
260
+ ```
261
+
3
262
  ## 7.2.0
4
263
 
5
264
  ### Minor Changes