react-router 0.0.0-experimental-0fd8a0272 → 0.0.0-experimental-573acd4d4

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,47 @@
1
1
  # `react-router`
2
2
 
3
+ ## 7.5.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Fix single fetch bug where no revalidation request would be made when navigating upwards to a reused parent route ([#13253](https://github.com/remix-run/react-router/pull/13253))
8
+
9
+ - When using the object-based `route.lazy` API, the `HydrateFallback` and `hydrateFallbackElement` properties are now skipped when lazy loading routes after hydration. ([#13376](https://github.com/remix-run/react-router/pull/13376))
10
+
11
+ If you move the code for these properties into a separate file, you can use this optimization to avoid downloading unused hydration code. For example:
12
+
13
+ ```ts
14
+ createBrowserRouter([
15
+ {
16
+ path: "/show/:showId",
17
+ lazy: {
18
+ loader: async () => (await import("./show.loader.js")).loader,
19
+ Component: async () => (await import("./show.component.js")).Component,
20
+ HydrateFallback: async () =>
21
+ (await import("./show.hydrate-fallback.js")).HydrateFallback,
22
+ },
23
+ },
24
+ ]);
25
+ ```
26
+
27
+ - Properly revalidate prerendered paths when param values change ([#13380](https://github.com/remix-run/react-router/pull/13380))
28
+
29
+ - UNSTABLE: Add a new `unstable_runClientMiddleware` argument to `dataStrategy` to enable middleware execution in custom `dataStrategy` implementations ([#13395](https://github.com/remix-run/react-router/pull/13395))
30
+
31
+ - UNSTABLE: Add better error messaging when `getLoadContext` is not updated to return a `Map`" ([#13242](https://github.com/remix-run/react-router/pull/13242))
32
+
33
+ - Do not automatically add `null` to `staticHandler.query()` `context.loaderData` if routes do not have loaders ([#13223](https://github.com/remix-run/react-router/pull/13223))
34
+
35
+ - This was a Remix v2 implementation detail inadvertently left in for React Router v7
36
+ - Now that we allow returning `undefined` from loaders, our prior check of `loaderData[routeId] !== undefined` was no longer sufficient and was changed to a `routeId in loaderData` check - these `null` values can cause issues for this new check
37
+ - ⚠️ This could be a "breaking bug fix" for you if you are doing manual SSR with `createStaticHandler()`/`<StaticRouterProvider>`, and using `context.loaderData` to control `<RouterProvider>` hydration behavior on the client
38
+
39
+ - Fix prerendering when a loader returns a redirect ([#13365](https://github.com/remix-run/react-router/pull/13365))
40
+
41
+ - UNSTABLE: Update context type for `LoaderFunctionArgs`/`ActionFunctionArgs` when middleware is enabled ([#13381](https://github.com/remix-run/react-router/pull/13381))
42
+
43
+ - Add support for the new `unstable_shouldCallHandler`/`unstable_shouldRevalidateArgs` APIs in `dataStrategy` ([#13253](https://github.com/remix-run/react-router/pull/13253))
44
+
3
45
  ## 7.5.0
4
46
 
5
47
  ### Minor Changes
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v0.0.0-experimental-0fd8a0272
2
+ * react-router v0.0.0-experimental-573acd4d4
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -7982,7 +7982,7 @@ function mergeRefs(...refs) {
7982
7982
  var isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement !== "undefined";
7983
7983
  try {
7984
7984
  if (isBrowser) {
7985
- window.__reactRouterVersion = "0.0.0-experimental-0fd8a0272";
7985
+ window.__reactRouterVersion = "0.0.0-experimental-573acd4d4";
7986
7986
  }
7987
7987
  } catch (e) {
7988
7988
  }
@@ -10672,16 +10672,12 @@ function deserializeErrors2(errors) {
10672
10672
  }
10673
10673
 
10674
10674
  // lib/dom/ssr/hydration.tsx
10675
- function getHydrationData(state, routes, getRouteInfo, isSpaMode) {
10675
+ function getHydrationData(state, routes, getRouteInfo, location2, basename, isSpaMode) {
10676
10676
  let hydrationData = {
10677
10677
  ...state,
10678
10678
  loaderData: { ...state.loaderData }
10679
10679
  };
10680
- let initialMatches = matchRoutes(
10681
- routes,
10682
- window.location,
10683
- window.__reactRouterContext?.basename
10684
- );
10680
+ let initialMatches = matchRoutes(routes, location2, basename);
10685
10681
  if (initialMatches) {
10686
10682
  for (let match of initialMatches) {
10687
10683
  let routeId = match.route.id;
@@ -10821,6 +10817,8 @@ function createRouterFromPayload({
10821
10817
  hasHydrateFallback: match.hydrateFallbackElement != null
10822
10818
  };
10823
10819
  },
10820
+ payload.location,
10821
+ void 0,
10824
10822
  false
10825
10823
  ),
10826
10824
  async patchRoutesOnNavigation({ patch, path, signal }) {
@@ -10855,9 +10853,9 @@ function createRouterFromPayload({
10855
10853
  } else {
10856
10854
  window.__routerInitialized = false;
10857
10855
  }
10858
- let lastLocationKey = window.__router.state.location.key;
10859
- window.__router.subscribe(({ location: location2 }) => {
10860
- if (location2.key !== lastLocationKey) {
10856
+ let lastLoaderData = void 0;
10857
+ window.__router.subscribe(({ loaderData, actionData }) => {
10858
+ if (lastLoaderData !== loaderData) {
10861
10859
  window.__routerActionID = (window.__routerActionID ?? (window.__routerActionID = 0)) + 1;
10862
10860
  }
10863
10861
  });
@@ -11100,7 +11098,7 @@ function injectRSCPayload(rscStream) {
11100
11098
  let timeout = null;
11101
11099
  function flushBufferedChunks(controller) {
11102
11100
  for (let chunk of buffered) {
11103
- let buf = decoder.decode(chunk);
11101
+ let buf = decoder.decode(chunk, { stream: true });
11104
11102
  if (buf.endsWith(trailer)) {
11105
11103
  buf = buf.slice(0, -trailer.length);
11106
11104
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v0.0.0-experimental-0fd8a0272
2
+ * react-router v0.0.0-experimental-573acd4d4
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -6129,16 +6129,12 @@ function deserializeErrors(errors) {
6129
6129
  }
6130
6130
 
6131
6131
  // lib/dom/ssr/hydration.tsx
6132
- function getHydrationData(state, routes, getRouteInfo, isSpaMode) {
6132
+ function getHydrationData(state, routes, getRouteInfo, location, basename, isSpaMode) {
6133
6133
  let hydrationData = {
6134
6134
  ...state,
6135
6135
  loaderData: { ...state.loaderData }
6136
6136
  };
6137
- let initialMatches = matchRoutes(
6138
- routes,
6139
- window.location,
6140
- window.__reactRouterContext?.basename
6141
- );
6137
+ let initialMatches = matchRoutes(routes, location, basename);
6142
6138
  if (initialMatches) {
6143
6139
  for (let match of initialMatches) {
6144
6140
  let routeId = match.route.id;
@@ -6244,6 +6240,8 @@ function createHydratedRouter({
6244
6240
  hasLoader: ssrInfo.manifest.routes[routeId]?.hasLoader === true,
6245
6241
  hasHydrateFallback: ssrInfo.routeModules[routeId]?.HydrateFallback != null
6246
6242
  }),
6243
+ window.location,
6244
+ window.__reactRouterContext?.basename,
6247
6245
  ssrInfo.context.isSpaMode
6248
6246
  );
6249
6247
  if (hydrationData && hydrationData.errors) {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v0.0.0-experimental-0fd8a0272
2
+ * react-router v0.0.0-experimental-573acd4d4
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -25,7 +25,7 @@ import {
25
25
  invariant,
26
26
  mapRouteProperties,
27
27
  useFogOFWarDiscovery
28
- } from "./chunk-E7S3F3DO.mjs";
28
+ } from "./chunk-6DVU7PCU.mjs";
29
29
 
30
30
  // lib/dom-export/dom-router-provider.tsx
31
31
  import * as React from "react";
@@ -115,6 +115,8 @@ function createHydratedRouter({
115
115
  hasLoader: ssrInfo.manifest.routes[routeId]?.hasLoader === true,
116
116
  hasHydrateFallback: ssrInfo.routeModules[routeId]?.HydrateFallback != null
117
117
  }),
118
+ window.location,
119
+ window.__reactRouterContext?.basename,
118
120
  ssrInfo.context.isSpaMode
119
121
  );
120
122
  if (hydrationData && hydrationData.errors) {
@@ -845,7 +845,7 @@ declare function getHydrationData(state: {
845
845
  clientLoader: ClientLoaderFunction | undefined;
846
846
  hasLoader: boolean;
847
847
  hasHydrateFallback: boolean;
848
- }, isSpaMode: boolean): HydrationState;
848
+ }, location: Path, basename: string | undefined, isSpaMode: boolean): HydrationState;
849
849
 
850
850
  declare function routeServerRequest(request: Request, requestServer: (request: Request) => Promise<Response>, decode: (body: ReadableStream<Uint8Array>) => Promise<ServerPayload>, renderHTML: (payload: ServerPayload) => ReadableStream<Uint8Array> | Promise<ReadableStream<Uint8Array>>): Promise<Response>;
851
851
  declare function ServerStaticRouter({ payload }: {
@@ -845,7 +845,7 @@ declare function getHydrationData(state: {
845
845
  clientLoader: ClientLoaderFunction | undefined;
846
846
  hasLoader: boolean;
847
847
  hasHydrateFallback: boolean;
848
- }, isSpaMode: boolean): HydrationState;
848
+ }, location: Path, basename: string | undefined, isSpaMode: boolean): HydrationState;
849
849
 
850
850
  declare function routeServerRequest(request: Request, requestServer: (request: Request) => Promise<Response>, decode: (body: ReadableStream<Uint8Array>) => Promise<ServerPayload>, renderHTML: (payload: ServerPayload) => ReadableStream<Uint8Array> | Promise<ReadableStream<Uint8Array>>): Promise<Response>;
851
851
  declare function ServerStaticRouter({ payload }: {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v0.0.0-experimental-0fd8a0272
2
+ * react-router v0.0.0-experimental-573acd4d4
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -8139,7 +8139,7 @@ function mergeRefs(...refs) {
8139
8139
  var isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement !== "undefined";
8140
8140
  try {
8141
8141
  if (isBrowser) {
8142
- window.__reactRouterVersion = "0.0.0-experimental-0fd8a0272";
8142
+ window.__reactRouterVersion = "0.0.0-experimental-573acd4d4";
8143
8143
  }
8144
8144
  } catch (e) {
8145
8145
  }
@@ -10829,16 +10829,12 @@ function deserializeErrors2(errors) {
10829
10829
  }
10830
10830
 
10831
10831
  // lib/dom/ssr/hydration.tsx
10832
- function getHydrationData(state, routes, getRouteInfo, isSpaMode) {
10832
+ function getHydrationData(state, routes, getRouteInfo, location2, basename, isSpaMode) {
10833
10833
  let hydrationData = {
10834
10834
  ...state,
10835
10835
  loaderData: { ...state.loaderData }
10836
10836
  };
10837
- let initialMatches = matchRoutes(
10838
- routes,
10839
- window.location,
10840
- window.__reactRouterContext?.basename
10841
- );
10837
+ let initialMatches = matchRoutes(routes, location2, basename);
10842
10838
  if (initialMatches) {
10843
10839
  for (let match of initialMatches) {
10844
10840
  let routeId = match.route.id;
@@ -10978,6 +10974,8 @@ function createRouterFromPayload({
10978
10974
  hasHydrateFallback: match.hydrateFallbackElement != null
10979
10975
  };
10980
10976
  },
10977
+ payload.location,
10978
+ void 0,
10981
10979
  false
10982
10980
  ),
10983
10981
  async patchRoutesOnNavigation({ patch, path, signal }) {
@@ -11012,9 +11010,9 @@ function createRouterFromPayload({
11012
11010
  } else {
11013
11011
  window.__routerInitialized = false;
11014
11012
  }
11015
- let lastLocationKey = window.__router.state.location.key;
11016
- window.__router.subscribe(({ location: location2 }) => {
11017
- if (location2.key !== lastLocationKey) {
11013
+ let lastLoaderData = void 0;
11014
+ window.__router.subscribe(({ loaderData, actionData }) => {
11015
+ if (lastLoaderData !== loaderData) {
11018
11016
  window.__routerActionID = (window.__routerActionID ?? (window.__routerActionID = 0)) + 1;
11019
11017
  }
11020
11018
  });
@@ -11257,7 +11255,7 @@ function injectRSCPayload(rscStream) {
11257
11255
  let timeout = null;
11258
11256
  function flushBufferedChunks(controller) {
11259
11257
  for (let chunk of buffered) {
11260
- let buf = decoder.decode(chunk);
11258
+ let buf = decoder.decode(chunk, { stream: true });
11261
11259
  if (buf.endsWith(trailer)) {
11262
11260
  buf = buf.slice(0, -trailer.length);
11263
11261
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v0.0.0-experimental-0fd8a0272
2
+ * react-router v0.0.0-experimental-573acd4d4
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -132,7 +132,7 @@ import {
132
132
  useSearchParams,
133
133
  useSubmit,
134
134
  useViewTransitionState
135
- } from "./chunk-E7S3F3DO.mjs";
135
+ } from "./chunk-6DVU7PCU.mjs";
136
136
  export {
137
137
  Await,
138
138
  BrowserRouter,
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v0.0.0-experimental-0fd8a0272
2
+ * react-router v0.0.0-experimental-573acd4d4
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v0.0.0-experimental-0fd8a0272
2
+ * react-router v0.0.0-experimental-573acd4d4
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1526,12 +1526,14 @@ type ServerMatch = {
1526
1526
  payload: ServerPayload;
1527
1527
  };
1528
1528
  type DecodeCallServerFunction = (id: string, reply: FormData | string) => Promise<() => Promise<unknown>>;
1529
- declare function matchServerRequest({ decodeCallServer, onError, request, routes, }: {
1529
+ type DecodeFormActionFunction = (formData: FormData) => Promise<() => Promise<void>>;
1530
+ declare function matchServerRequest({ decodeCallServer, decodeFormAction, onError, request, routes, }: {
1530
1531
  decodeCallServer?: DecodeCallServerFunction;
1532
+ decodeFormAction?: DecodeFormActionFunction;
1531
1533
  onError?: (error: unknown) => void;
1532
1534
  request: Request;
1533
1535
  routes: ServerRouteObject[];
1534
- }): Promise<ServerMatch | Response>;
1536
+ }): Promise<ServerMatch>;
1535
1537
  declare function isReactServerRequest(url: URL): boolean;
1536
1538
 
1537
- export { type DecodeCallServerFunction, type ServerManifestPayload, type ServerMatch, type ServerPayload, type ServerRenderPayload, type RenderedRoute as ServerRouteManifest, type ServerRouteMatch, type ServerRouteObject, createStaticHandler, data, isReactServerRequest, matchRoutes, matchServerRequest, redirect, redirectDocument, replace };
1539
+ export { type DecodeCallServerFunction, type DecodeFormActionFunction, type ServerManifestPayload, type ServerMatch, type ServerPayload, type ServerRenderPayload, type RenderedRoute as ServerRouteManifest, type ServerRouteMatch, type ServerRouteObject, createStaticHandler, data, isReactServerRequest, matchRoutes, matchServerRequest, redirect, redirectDocument, replace };
@@ -1526,12 +1526,14 @@ type ServerMatch = {
1526
1526
  payload: ServerPayload;
1527
1527
  };
1528
1528
  type DecodeCallServerFunction = (id: string, reply: FormData | string) => Promise<() => Promise<unknown>>;
1529
- declare function matchServerRequest({ decodeCallServer, onError, request, routes, }: {
1529
+ type DecodeFormActionFunction = (formData: FormData) => Promise<() => Promise<void>>;
1530
+ declare function matchServerRequest({ decodeCallServer, decodeFormAction, onError, request, routes, }: {
1530
1531
  decodeCallServer?: DecodeCallServerFunction;
1532
+ decodeFormAction?: DecodeFormActionFunction;
1531
1533
  onError?: (error: unknown) => void;
1532
1534
  request: Request;
1533
1535
  routes: ServerRouteObject[];
1534
- }): Promise<ServerMatch | Response>;
1536
+ }): Promise<ServerMatch>;
1535
1537
  declare function isReactServerRequest(url: URL): boolean;
1536
1538
 
1537
- export { type DecodeCallServerFunction, type ServerManifestPayload, type ServerMatch, type ServerPayload, type ServerRenderPayload, type RenderedRoute as ServerRouteManifest, type ServerRouteMatch, type ServerRouteObject, createStaticHandler, data, isReactServerRequest, matchRoutes, matchServerRequest, redirect, redirectDocument, replace };
1539
+ export { type DecodeCallServerFunction, type DecodeFormActionFunction, type ServerManifestPayload, type ServerMatch, type ServerPayload, type ServerRenderPayload, type RenderedRoute as ServerRouteManifest, type ServerRouteMatch, type ServerRouteObject, createStaticHandler, data, isReactServerRequest, matchRoutes, matchServerRequest, redirect, redirectDocument, replace };
@@ -23,7 +23,7 @@ function _interopNamespace(e) {
23
23
  var React__namespace = /*#__PURE__*/_interopNamespace(React);
24
24
 
25
25
  /**
26
- * react-router v0.0.0-experimental-0fd8a0272
26
+ * react-router v0.0.0-experimental-573acd4d4
27
27
  *
28
28
  * Copyright (c) Remix Software Inc.
29
29
  *
@@ -2001,6 +2001,7 @@ function getTargetMatch(matches, location) {
2001
2001
  }
2002
2002
  async function matchServerRequest({
2003
2003
  decodeCallServer,
2004
+ decodeFormAction,
2004
2005
  onError,
2005
2006
  request,
2006
2007
  routes
@@ -2011,9 +2012,6 @@ async function matchServerRequest({
2011
2012
  routes,
2012
2013
  url.pathname.replace(/\.manifest$/, "")
2013
2014
  );
2014
- if (!matches?.length) {
2015
- return new Response("Not found", { status: 404 });
2016
- }
2017
2015
  return {
2018
2016
  statusCode: 200,
2019
2017
  headers: new Headers({
@@ -2023,12 +2021,12 @@ async function matchServerRequest({
2023
2021
  payload: {
2024
2022
  type: "manifest",
2025
2023
  matches: await Promise.all(
2026
- matches.map((m, i) => getRoute(m.route, matches[i - 1]?.route.id))
2024
+ matches?.map((m, i) => getRoute(m.route, matches[i - 1]?.route.id)) ?? []
2027
2025
  ),
2028
2026
  patches: await getAdditionalRoutePatches(
2029
2027
  url.pathname,
2030
2028
  routes,
2031
- matches.map((m) => m.route.id)
2029
+ matches?.map((m) => m.route.id) ?? []
2032
2030
  )
2033
2031
  }
2034
2032
  };
@@ -2056,6 +2054,27 @@ async function matchServerRequest({
2056
2054
  signal: request.signal
2057
2055
  });
2058
2056
  }
2057
+ if (request.method === "POST") {
2058
+ const formData = await request.formData();
2059
+ if (Array.from(formData.keys()).some((key) => key.startsWith("$ACTION_ID_"))) {
2060
+ if (!decodeFormAction) {
2061
+ throw new Error(
2062
+ "Cannot handle form actions without a decodeFormAction function"
2063
+ );
2064
+ }
2065
+ const action = await decodeFormAction(formData);
2066
+ try {
2067
+ await action();
2068
+ } catch (error) {
2069
+ onError?.(error);
2070
+ }
2071
+ request = new Request(request.url, {
2072
+ method: "GET",
2073
+ headers: request.headers,
2074
+ signal: request.signal
2075
+ });
2076
+ }
2077
+ }
2059
2078
  const getRenderPayload = async () => {
2060
2079
  const handler = createStaticHandler(routes);
2061
2080
  let isSubmission = isMutationMethod(request.method);
@@ -2188,9 +2207,6 @@ async function matchServerRequest({
2188
2207
  } : await getRenderPayload()
2189
2208
  };
2190
2209
  } catch (error) {
2191
- if (typeof error === "object" && error instanceof Response) {
2192
- return error;
2193
- }
2194
2210
  throw error;
2195
2211
  }
2196
2212
  }
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
2
 
3
3
  /**
4
- * react-router v0.0.0-experimental-0fd8a0272
4
+ * react-router v0.0.0-experimental-573acd4d4
5
5
  *
6
6
  * Copyright (c) Remix Software Inc.
7
7
  *
@@ -1979,6 +1979,7 @@ function getTargetMatch(matches, location) {
1979
1979
  }
1980
1980
  async function matchServerRequest({
1981
1981
  decodeCallServer,
1982
+ decodeFormAction,
1982
1983
  onError,
1983
1984
  request,
1984
1985
  routes
@@ -1989,9 +1990,6 @@ async function matchServerRequest({
1989
1990
  routes,
1990
1991
  url.pathname.replace(/\.manifest$/, "")
1991
1992
  );
1992
- if (!matches?.length) {
1993
- return new Response("Not found", { status: 404 });
1994
- }
1995
1993
  return {
1996
1994
  statusCode: 200,
1997
1995
  headers: new Headers({
@@ -2001,12 +1999,12 @@ async function matchServerRequest({
2001
1999
  payload: {
2002
2000
  type: "manifest",
2003
2001
  matches: await Promise.all(
2004
- matches.map((m, i) => getRoute(m.route, matches[i - 1]?.route.id))
2002
+ matches?.map((m, i) => getRoute(m.route, matches[i - 1]?.route.id)) ?? []
2005
2003
  ),
2006
2004
  patches: await getAdditionalRoutePatches(
2007
2005
  url.pathname,
2008
2006
  routes,
2009
- matches.map((m) => m.route.id)
2007
+ matches?.map((m) => m.route.id) ?? []
2010
2008
  )
2011
2009
  }
2012
2010
  };
@@ -2034,6 +2032,27 @@ async function matchServerRequest({
2034
2032
  signal: request.signal
2035
2033
  });
2036
2034
  }
2035
+ if (request.method === "POST") {
2036
+ const formData = await request.formData();
2037
+ if (Array.from(formData.keys()).some((key) => key.startsWith("$ACTION_ID_"))) {
2038
+ if (!decodeFormAction) {
2039
+ throw new Error(
2040
+ "Cannot handle form actions without a decodeFormAction function"
2041
+ );
2042
+ }
2043
+ const action = await decodeFormAction(formData);
2044
+ try {
2045
+ await action();
2046
+ } catch (error) {
2047
+ onError?.(error);
2048
+ }
2049
+ request = new Request(request.url, {
2050
+ method: "GET",
2051
+ headers: request.headers,
2052
+ signal: request.signal
2053
+ });
2054
+ }
2055
+ }
2037
2056
  const getRenderPayload = async () => {
2038
2057
  const handler = createStaticHandler(routes);
2039
2058
  let isSubmission = isMutationMethod(request.method);
@@ -2166,9 +2185,6 @@ async function matchServerRequest({
2166
2185
  } : await getRenderPayload()
2167
2186
  };
2168
2187
  } catch (error) {
2169
- if (typeof error === "object" && error instanceof Response) {
2170
- return error;
2171
- }
2172
2188
  throw error;
2173
2189
  }
2174
2190
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v0.0.0-experimental-0fd8a0272
2
+ * react-router v0.0.0-experimental-573acd4d4
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -7982,7 +7982,7 @@ function mergeRefs(...refs) {
7982
7982
  var isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement !== "undefined";
7983
7983
  try {
7984
7984
  if (isBrowser) {
7985
- window.__reactRouterVersion = "0.0.0-experimental-0fd8a0272";
7985
+ window.__reactRouterVersion = "0.0.0-experimental-573acd4d4";
7986
7986
  }
7987
7987
  } catch (e) {
7988
7988
  }
@@ -10672,16 +10672,12 @@ function deserializeErrors2(errors) {
10672
10672
  }
10673
10673
 
10674
10674
  // lib/dom/ssr/hydration.tsx
10675
- function getHydrationData(state, routes, getRouteInfo, isSpaMode) {
10675
+ function getHydrationData(state, routes, getRouteInfo, location2, basename, isSpaMode) {
10676
10676
  let hydrationData = {
10677
10677
  ...state,
10678
10678
  loaderData: { ...state.loaderData }
10679
10679
  };
10680
- let initialMatches = matchRoutes(
10681
- routes,
10682
- window.location,
10683
- window.__reactRouterContext?.basename
10684
- );
10680
+ let initialMatches = matchRoutes(routes, location2, basename);
10685
10681
  if (initialMatches) {
10686
10682
  for (let match of initialMatches) {
10687
10683
  let routeId = match.route.id;
@@ -10821,6 +10817,8 @@ function createRouterFromPayload({
10821
10817
  hasHydrateFallback: match.hydrateFallbackElement != null
10822
10818
  };
10823
10819
  },
10820
+ payload.location,
10821
+ void 0,
10824
10822
  false
10825
10823
  ),
10826
10824
  async patchRoutesOnNavigation({ patch, path, signal }) {
@@ -10855,9 +10853,9 @@ function createRouterFromPayload({
10855
10853
  } else {
10856
10854
  window.__routerInitialized = false;
10857
10855
  }
10858
- let lastLocationKey = window.__router.state.location.key;
10859
- window.__router.subscribe(({ location: location2 }) => {
10860
- if (location2.key !== lastLocationKey) {
10856
+ let lastLoaderData = void 0;
10857
+ window.__router.subscribe(({ loaderData, actionData }) => {
10858
+ if (lastLoaderData !== loaderData) {
10861
10859
  window.__routerActionID = (window.__routerActionID ?? (window.__routerActionID = 0)) + 1;
10862
10860
  }
10863
10861
  });
@@ -11100,7 +11098,7 @@ function injectRSCPayload(rscStream) {
11100
11098
  let timeout = null;
11101
11099
  function flushBufferedChunks(controller) {
11102
11100
  for (let chunk of buffered) {
11103
- let buf = decoder.decode(chunk);
11101
+ let buf = decoder.decode(chunk, { stream: true });
11104
11102
  if (buf.endsWith(trailer)) {
11105
11103
  buf = buf.slice(0, -trailer.length);
11106
11104
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v0.0.0-experimental-0fd8a0272
2
+ * react-router v0.0.0-experimental-573acd4d4
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -6129,16 +6129,12 @@ function deserializeErrors(errors) {
6129
6129
  }
6130
6130
 
6131
6131
  // lib/dom/ssr/hydration.tsx
6132
- function getHydrationData(state, routes, getRouteInfo, isSpaMode) {
6132
+ function getHydrationData(state, routes, getRouteInfo, location, basename, isSpaMode) {
6133
6133
  let hydrationData = {
6134
6134
  ...state,
6135
6135
  loaderData: { ...state.loaderData }
6136
6136
  };
6137
- let initialMatches = matchRoutes(
6138
- routes,
6139
- window.location,
6140
- window.__reactRouterContext?.basename
6141
- );
6137
+ let initialMatches = matchRoutes(routes, location, basename);
6142
6138
  if (initialMatches) {
6143
6139
  for (let match of initialMatches) {
6144
6140
  let routeId = match.route.id;
@@ -6244,6 +6240,8 @@ function createHydratedRouter({
6244
6240
  hasLoader: ssrInfo.manifest.routes[routeId]?.hasLoader === true,
6245
6241
  hasHydrateFallback: ssrInfo.routeModules[routeId]?.HydrateFallback != null
6246
6242
  }),
6243
+ window.location,
6244
+ window.__reactRouterContext?.basename,
6247
6245
  ssrInfo.context.isSpaMode
6248
6246
  );
6249
6247
  if (hydrationData && hydrationData.errors) {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v0.0.0-experimental-0fd8a0272
2
+ * react-router v0.0.0-experimental-573acd4d4
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -25,7 +25,7 @@ import {
25
25
  invariant,
26
26
  mapRouteProperties,
27
27
  useFogOFWarDiscovery
28
- } from "./chunk-OBBSTJVM.mjs";
28
+ } from "./chunk-ZHQUHC3T.mjs";
29
29
 
30
30
  // lib/dom-export/dom-router-provider.tsx
31
31
  import * as React from "react";
@@ -115,6 +115,8 @@ function createHydratedRouter({
115
115
  hasLoader: ssrInfo.manifest.routes[routeId]?.hasLoader === true,
116
116
  hasHydrateFallback: ssrInfo.routeModules[routeId]?.HydrateFallback != null
117
117
  }),
118
+ window.location,
119
+ window.__reactRouterContext?.basename,
118
120
  ssrInfo.context.isSpaMode
119
121
  );
120
122
  if (hydrationData && hydrationData.errors) {
@@ -845,7 +845,7 @@ declare function getHydrationData(state: {
845
845
  clientLoader: ClientLoaderFunction | undefined;
846
846
  hasLoader: boolean;
847
847
  hasHydrateFallback: boolean;
848
- }, isSpaMode: boolean): HydrationState;
848
+ }, location: Path, basename: string | undefined, isSpaMode: boolean): HydrationState;
849
849
 
850
850
  declare function routeServerRequest(request: Request, requestServer: (request: Request) => Promise<Response>, decode: (body: ReadableStream<Uint8Array>) => Promise<ServerPayload>, renderHTML: (payload: ServerPayload) => ReadableStream<Uint8Array> | Promise<ReadableStream<Uint8Array>>): Promise<Response>;
851
851
  declare function ServerStaticRouter({ payload }: {
@@ -845,7 +845,7 @@ declare function getHydrationData(state: {
845
845
  clientLoader: ClientLoaderFunction | undefined;
846
846
  hasLoader: boolean;
847
847
  hasHydrateFallback: boolean;
848
- }, isSpaMode: boolean): HydrationState;
848
+ }, location: Path, basename: string | undefined, isSpaMode: boolean): HydrationState;
849
849
 
850
850
  declare function routeServerRequest(request: Request, requestServer: (request: Request) => Promise<Response>, decode: (body: ReadableStream<Uint8Array>) => Promise<ServerPayload>, renderHTML: (payload: ServerPayload) => ReadableStream<Uint8Array> | Promise<ReadableStream<Uint8Array>>): Promise<Response>;
851
851
  declare function ServerStaticRouter({ payload }: {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v0.0.0-experimental-0fd8a0272
2
+ * react-router v0.0.0-experimental-573acd4d4
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -8139,7 +8139,7 @@ function mergeRefs(...refs) {
8139
8139
  var isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement !== "undefined";
8140
8140
  try {
8141
8141
  if (isBrowser) {
8142
- window.__reactRouterVersion = "0.0.0-experimental-0fd8a0272";
8142
+ window.__reactRouterVersion = "0.0.0-experimental-573acd4d4";
8143
8143
  }
8144
8144
  } catch (e) {
8145
8145
  }
@@ -10829,16 +10829,12 @@ function deserializeErrors2(errors) {
10829
10829
  }
10830
10830
 
10831
10831
  // lib/dom/ssr/hydration.tsx
10832
- function getHydrationData(state, routes, getRouteInfo, isSpaMode) {
10832
+ function getHydrationData(state, routes, getRouteInfo, location2, basename, isSpaMode) {
10833
10833
  let hydrationData = {
10834
10834
  ...state,
10835
10835
  loaderData: { ...state.loaderData }
10836
10836
  };
10837
- let initialMatches = matchRoutes(
10838
- routes,
10839
- window.location,
10840
- window.__reactRouterContext?.basename
10841
- );
10837
+ let initialMatches = matchRoutes(routes, location2, basename);
10842
10838
  if (initialMatches) {
10843
10839
  for (let match of initialMatches) {
10844
10840
  let routeId = match.route.id;
@@ -10978,6 +10974,8 @@ function createRouterFromPayload({
10978
10974
  hasHydrateFallback: match.hydrateFallbackElement != null
10979
10975
  };
10980
10976
  },
10977
+ payload.location,
10978
+ void 0,
10981
10979
  false
10982
10980
  ),
10983
10981
  async patchRoutesOnNavigation({ patch, path, signal }) {
@@ -11012,9 +11010,9 @@ function createRouterFromPayload({
11012
11010
  } else {
11013
11011
  window.__routerInitialized = false;
11014
11012
  }
11015
- let lastLocationKey = window.__router.state.location.key;
11016
- window.__router.subscribe(({ location: location2 }) => {
11017
- if (location2.key !== lastLocationKey) {
11013
+ let lastLoaderData = void 0;
11014
+ window.__router.subscribe(({ loaderData, actionData }) => {
11015
+ if (lastLoaderData !== loaderData) {
11018
11016
  window.__routerActionID = (window.__routerActionID ?? (window.__routerActionID = 0)) + 1;
11019
11017
  }
11020
11018
  });
@@ -11257,7 +11255,7 @@ function injectRSCPayload(rscStream) {
11257
11255
  let timeout = null;
11258
11256
  function flushBufferedChunks(controller) {
11259
11257
  for (let chunk of buffered) {
11260
- let buf = decoder.decode(chunk);
11258
+ let buf = decoder.decode(chunk, { stream: true });
11261
11259
  if (buf.endsWith(trailer)) {
11262
11260
  buf = buf.slice(0, -trailer.length);
11263
11261
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v0.0.0-experimental-0fd8a0272
2
+ * react-router v0.0.0-experimental-573acd4d4
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -132,7 +132,7 @@ import {
132
132
  useSearchParams,
133
133
  useSubmit,
134
134
  useViewTransitionState
135
- } from "./chunk-OBBSTJVM.mjs";
135
+ } from "./chunk-ZHQUHC3T.mjs";
136
136
  export {
137
137
  Await,
138
138
  BrowserRouter,
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v0.0.0-experimental-0fd8a0272
2
+ * react-router v0.0.0-experimental-573acd4d4
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v0.0.0-experimental-0fd8a0272
2
+ * react-router v0.0.0-experimental-573acd4d4
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1526,12 +1526,14 @@ type ServerMatch = {
1526
1526
  payload: ServerPayload;
1527
1527
  };
1528
1528
  type DecodeCallServerFunction = (id: string, reply: FormData | string) => Promise<() => Promise<unknown>>;
1529
- declare function matchServerRequest({ decodeCallServer, onError, request, routes, }: {
1529
+ type DecodeFormActionFunction = (formData: FormData) => Promise<() => Promise<void>>;
1530
+ declare function matchServerRequest({ decodeCallServer, decodeFormAction, onError, request, routes, }: {
1530
1531
  decodeCallServer?: DecodeCallServerFunction;
1532
+ decodeFormAction?: DecodeFormActionFunction;
1531
1533
  onError?: (error: unknown) => void;
1532
1534
  request: Request;
1533
1535
  routes: ServerRouteObject[];
1534
- }): Promise<ServerMatch | Response>;
1536
+ }): Promise<ServerMatch>;
1535
1537
  declare function isReactServerRequest(url: URL): boolean;
1536
1538
 
1537
- export { type DecodeCallServerFunction, type ServerManifestPayload, type ServerMatch, type ServerPayload, type ServerRenderPayload, type RenderedRoute as ServerRouteManifest, type ServerRouteMatch, type ServerRouteObject, createStaticHandler, data, isReactServerRequest, matchRoutes, matchServerRequest, redirect, redirectDocument, replace };
1539
+ export { type DecodeCallServerFunction, type DecodeFormActionFunction, type ServerManifestPayload, type ServerMatch, type ServerPayload, type ServerRenderPayload, type RenderedRoute as ServerRouteManifest, type ServerRouteMatch, type ServerRouteObject, createStaticHandler, data, isReactServerRequest, matchRoutes, matchServerRequest, redirect, redirectDocument, replace };
@@ -1526,12 +1526,14 @@ type ServerMatch = {
1526
1526
  payload: ServerPayload;
1527
1527
  };
1528
1528
  type DecodeCallServerFunction = (id: string, reply: FormData | string) => Promise<() => Promise<unknown>>;
1529
- declare function matchServerRequest({ decodeCallServer, onError, request, routes, }: {
1529
+ type DecodeFormActionFunction = (formData: FormData) => Promise<() => Promise<void>>;
1530
+ declare function matchServerRequest({ decodeCallServer, decodeFormAction, onError, request, routes, }: {
1530
1531
  decodeCallServer?: DecodeCallServerFunction;
1532
+ decodeFormAction?: DecodeFormActionFunction;
1531
1533
  onError?: (error: unknown) => void;
1532
1534
  request: Request;
1533
1535
  routes: ServerRouteObject[];
1534
- }): Promise<ServerMatch | Response>;
1536
+ }): Promise<ServerMatch>;
1535
1537
  declare function isReactServerRequest(url: URL): boolean;
1536
1538
 
1537
- export { type DecodeCallServerFunction, type ServerManifestPayload, type ServerMatch, type ServerPayload, type ServerRenderPayload, type RenderedRoute as ServerRouteManifest, type ServerRouteMatch, type ServerRouteObject, createStaticHandler, data, isReactServerRequest, matchRoutes, matchServerRequest, redirect, redirectDocument, replace };
1539
+ export { type DecodeCallServerFunction, type DecodeFormActionFunction, type ServerManifestPayload, type ServerMatch, type ServerPayload, type ServerRenderPayload, type RenderedRoute as ServerRouteManifest, type ServerRouteMatch, type ServerRouteObject, createStaticHandler, data, isReactServerRequest, matchRoutes, matchServerRequest, redirect, redirectDocument, replace };
@@ -23,7 +23,7 @@ function _interopNamespace(e) {
23
23
  var React__namespace = /*#__PURE__*/_interopNamespace(React);
24
24
 
25
25
  /**
26
- * react-router v0.0.0-experimental-0fd8a0272
26
+ * react-router v0.0.0-experimental-573acd4d4
27
27
  *
28
28
  * Copyright (c) Remix Software Inc.
29
29
  *
@@ -2001,6 +2001,7 @@ function getTargetMatch(matches, location) {
2001
2001
  }
2002
2002
  async function matchServerRequest({
2003
2003
  decodeCallServer,
2004
+ decodeFormAction,
2004
2005
  onError,
2005
2006
  request,
2006
2007
  routes
@@ -2011,9 +2012,6 @@ async function matchServerRequest({
2011
2012
  routes,
2012
2013
  url.pathname.replace(/\.manifest$/, "")
2013
2014
  );
2014
- if (!matches?.length) {
2015
- return new Response("Not found", { status: 404 });
2016
- }
2017
2015
  return {
2018
2016
  statusCode: 200,
2019
2017
  headers: new Headers({
@@ -2023,12 +2021,12 @@ async function matchServerRequest({
2023
2021
  payload: {
2024
2022
  type: "manifest",
2025
2023
  matches: await Promise.all(
2026
- matches.map((m, i) => getRoute(m.route, matches[i - 1]?.route.id))
2024
+ matches?.map((m, i) => getRoute(m.route, matches[i - 1]?.route.id)) ?? []
2027
2025
  ),
2028
2026
  patches: await getAdditionalRoutePatches(
2029
2027
  url.pathname,
2030
2028
  routes,
2031
- matches.map((m) => m.route.id)
2029
+ matches?.map((m) => m.route.id) ?? []
2032
2030
  )
2033
2031
  }
2034
2032
  };
@@ -2056,6 +2054,27 @@ async function matchServerRequest({
2056
2054
  signal: request.signal
2057
2055
  });
2058
2056
  }
2057
+ if (request.method === "POST") {
2058
+ const formData = await request.formData();
2059
+ if (Array.from(formData.keys()).some((key) => key.startsWith("$ACTION_ID_"))) {
2060
+ if (!decodeFormAction) {
2061
+ throw new Error(
2062
+ "Cannot handle form actions without a decodeFormAction function"
2063
+ );
2064
+ }
2065
+ const action = await decodeFormAction(formData);
2066
+ try {
2067
+ await action();
2068
+ } catch (error) {
2069
+ onError?.(error);
2070
+ }
2071
+ request = new Request(request.url, {
2072
+ method: "GET",
2073
+ headers: request.headers,
2074
+ signal: request.signal
2075
+ });
2076
+ }
2077
+ }
2059
2078
  const getRenderPayload = async () => {
2060
2079
  const handler = createStaticHandler(routes);
2061
2080
  let isSubmission = isMutationMethod(request.method);
@@ -2188,9 +2207,6 @@ async function matchServerRequest({
2188
2207
  } : await getRenderPayload()
2189
2208
  };
2190
2209
  } catch (error) {
2191
- if (typeof error === "object" && error instanceof Response) {
2192
- return error;
2193
- }
2194
2210
  throw error;
2195
2211
  }
2196
2212
  }
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
2
 
3
3
  /**
4
- * react-router v0.0.0-experimental-0fd8a0272
4
+ * react-router v0.0.0-experimental-573acd4d4
5
5
  *
6
6
  * Copyright (c) Remix Software Inc.
7
7
  *
@@ -1979,6 +1979,7 @@ function getTargetMatch(matches, location) {
1979
1979
  }
1980
1980
  async function matchServerRequest({
1981
1981
  decodeCallServer,
1982
+ decodeFormAction,
1982
1983
  onError,
1983
1984
  request,
1984
1985
  routes
@@ -1989,9 +1990,6 @@ async function matchServerRequest({
1989
1990
  routes,
1990
1991
  url.pathname.replace(/\.manifest$/, "")
1991
1992
  );
1992
- if (!matches?.length) {
1993
- return new Response("Not found", { status: 404 });
1994
- }
1995
1993
  return {
1996
1994
  statusCode: 200,
1997
1995
  headers: new Headers({
@@ -2001,12 +1999,12 @@ async function matchServerRequest({
2001
1999
  payload: {
2002
2000
  type: "manifest",
2003
2001
  matches: await Promise.all(
2004
- matches.map((m, i) => getRoute(m.route, matches[i - 1]?.route.id))
2002
+ matches?.map((m, i) => getRoute(m.route, matches[i - 1]?.route.id)) ?? []
2005
2003
  ),
2006
2004
  patches: await getAdditionalRoutePatches(
2007
2005
  url.pathname,
2008
2006
  routes,
2009
- matches.map((m) => m.route.id)
2007
+ matches?.map((m) => m.route.id) ?? []
2010
2008
  )
2011
2009
  }
2012
2010
  };
@@ -2034,6 +2032,27 @@ async function matchServerRequest({
2034
2032
  signal: request.signal
2035
2033
  });
2036
2034
  }
2035
+ if (request.method === "POST") {
2036
+ const formData = await request.formData();
2037
+ if (Array.from(formData.keys()).some((key) => key.startsWith("$ACTION_ID_"))) {
2038
+ if (!decodeFormAction) {
2039
+ throw new Error(
2040
+ "Cannot handle form actions without a decodeFormAction function"
2041
+ );
2042
+ }
2043
+ const action = await decodeFormAction(formData);
2044
+ try {
2045
+ await action();
2046
+ } catch (error) {
2047
+ onError?.(error);
2048
+ }
2049
+ request = new Request(request.url, {
2050
+ method: "GET",
2051
+ headers: request.headers,
2052
+ signal: request.signal
2053
+ });
2054
+ }
2055
+ }
2037
2056
  const getRenderPayload = async () => {
2038
2057
  const handler = createStaticHandler(routes);
2039
2058
  let isSubmission = isMutationMethod(request.method);
@@ -2166,9 +2185,6 @@ async function matchServerRequest({
2166
2185
  } : await getRenderPayload()
2167
2186
  };
2168
2187
  } catch (error) {
2169
- if (typeof error === "object" && error instanceof Response) {
2170
- return error;
2171
- }
2172
2188
  throw error;
2173
2189
  }
2174
2190
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-router",
3
- "version": "0.0.0-experimental-0fd8a0272",
3
+ "version": "0.0.0-experimental-573acd4d4",
4
4
  "description": "Declarative routing for React",
5
5
  "keywords": [
6
6
  "react",