From 69debd1a33aa87924740ec199c4a598d4d1ebcae Mon Sep 17 00:00:00 2001
From: dfedoryshchev <64079946+dfedoryshchev@users.noreply.github.com>
Date: Tue, 14 Jul 2026 15:31:46 +0100
Subject: [PATCH 1/4] fix: apply NavLink pending state when the to prop has a
trailing slash (#15300)
---
.../patch.navlink-pending-trailing-slash.md | 1 +
.../__tests__/dom/nav-link-active-test.tsx | 39 +++++++++++++++++++
packages/react-router/lib/dom/lib.tsx | 2 +-
3 files changed, 41 insertions(+), 1 deletion(-)
create mode 100644 packages/react-router/.changes/patch.navlink-pending-trailing-slash.md
diff --git a/packages/react-router/.changes/patch.navlink-pending-trailing-slash.md b/packages/react-router/.changes/patch.navlink-pending-trailing-slash.md
new file mode 100644
index 0000000000..085ad0f54f
--- /dev/null
+++ b/packages/react-router/.changes/patch.navlink-pending-trailing-slash.md
@@ -0,0 +1 @@
+Fix `NavLink` not applying its `pending` state when `to` has a trailing slash
diff --git a/packages/react-router/__tests__/dom/nav-link-active-test.tsx b/packages/react-router/__tests__/dom/nav-link-active-test.tsx
index 6213df570b..f5de0a4a71 100644
--- a/packages/react-router/__tests__/dom/nav-link-active-test.tsx
+++ b/packages/react-router/__tests__/dom/nav-link-active-test.tsx
@@ -696,6 +696,45 @@ describe("NavLink using a data router", () => {
expect(screen.getByText("Link to Bar").className).toBe("active");
});
+ it("applies the 'pending' className to a NavLink whose 'to' has a trailing slash", async () => {
+ let dfd = createDeferred();
+ let router = createBrowserRouter(
+ createRoutesFromElements(
+ }>
+ }>
+ dfd.promise}
+ element={Child page
}
+ />
+
+ ,
+ ),
+ {
+ window: getWindow("/"),
+ },
+ );
+ render();
+
+ function Layout() {
+ return (
+ <>
+ Home
+ Child
+
+ >
+ );
+ }
+
+ expect(screen.getByText("Home").className).toBe("");
+
+ fireEvent.click(screen.getByText("Child"));
+ expect(screen.getByText("Home").className).toBe("pending");
+
+ dfd.resolve(null);
+ await waitFor(() => screen.getByText("Child page"));
+ });
+
it("applies its className correctly when provided as a function", async () => {
let dfd = createDeferred();
let router = createBrowserRouter(
diff --git a/packages/react-router/lib/dom/lib.tsx b/packages/react-router/lib/dom/lib.tsx
index 6e01cb1584..47e66196e6 100644
--- a/packages/react-router/lib/dom/lib.tsx
+++ b/packages/react-router/lib/dom/lib.tsx
@@ -1690,7 +1690,7 @@ export const NavLink = React.forwardRef(
(nextLocationPathname === toPathname ||
(!end &&
nextLocationPathname.startsWith(toPathname) &&
- nextLocationPathname.charAt(toPathname.length) === "/"));
+ nextLocationPathname.charAt(endSlashPosition) === "/"));
let renderProps = {
isActive,
From baa9ba617b9df1114359439013462cc3486d5b72 Mon Sep 17 00:00:00 2001
From: Nowell Strite
Date: Tue, 14 Jul 2026 11:18:22 -0400
Subject: [PATCH 2/4] fix: encode path params per RFC 3986 path-segment rules
in href/generatePath (#15310)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* fix: encode path params per RFC 3986 path-segment rules in href/generatePath
Follow-up to #15277, which fixed `href()` to URL-encode param values to
match `generatePath()`. Both now encode with `encodeURIComponent`, which
implements *query-string* escaping — a stricter rule than URL paths
require. This over-escapes characters that RFC 3986 explicitly allows
literally in a path segment:
pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
https://datatracker.ietf.org/doc/html/rfc3986#section-3.3
`$ & + , ; = : @` only act as delimiters in a query string; in a path
segment they carry no special meaning, and browsers keep them literal in
`location.pathname`. Encoding them needlessly rewrites URLs:
href("/releases/:v", { v: "1.0.0+1" })
// before: /releases/1.0.0%2B1
// after: /releases/1.0.0+1
which breaks apps that compare generated URLs against
`window.location.pathname` (the browser reports the literal `+`), churns
canonical/shareable URLs, and makes `href()` output disagree with what
users see in the address bar.
Changes:
- Add an internal `encodePathParam()` that escapes structural/unsafe
characters (`/ ? # %`, whitespace, non-ASCII) exactly as before, but
restores the RFC 3986 pchar set that `encodeURIComponent` over-escapes
- Use it for named params in `generatePath()` and for named params and
splat segments in `href()`
- Document path-segment vs query-string encoding semantics (with the RFC
reference) in the `href()` and `generatePath()` JSDoc
- Update and extend unit tests; add a change file
Behavior is unchanged for every character outside `$ & + , ; = : @`, and
`generatePath()`'s splat values remain un-encoded, as before.
Co-Authored-By: Claude Fable 5
* Update docs
---------
Co-authored-by: Claude Fable 5
Co-authored-by: Matt Brophy
---
.../patch.encode-path-params-pchar.md | 4 ++
.../__tests__/generatePath-test.tsx | 22 +++++++
packages/react-router/__tests__/href-test.ts | 27 +++++++-
packages/react-router/lib/href.ts | 37 ++++++++---
packages/react-router/lib/router/utils.ts | 61 ++++++++++++++++++-
5 files changed, 138 insertions(+), 13 deletions(-)
create mode 100644 packages/react-router/.changes/patch.encode-path-params-pchar.md
diff --git a/packages/react-router/.changes/patch.encode-path-params-pchar.md b/packages/react-router/.changes/patch.encode-path-params-pchar.md
new file mode 100644
index 0000000000..811f55cafe
--- /dev/null
+++ b/packages/react-router/.changes/patch.encode-path-params-pchar.md
@@ -0,0 +1,4 @@
+Encode path params in `href`/`generatePath` per RFC 3986 path-segment rules instead of `encodeURIComponent`
+
+- Characters that are valid literally in a path segment (`$ & + , ; = : @` — RFC 3986 `pchar`) are no longer percent-encoded, so values like a semver build `1.0.0+1` interpolate unchanged instead of becoming `1.0.0%2B1`
+- Structural/unsafe characters (`/ ? # %`, whitespace, non-ASCII) are still escaped exactly as before
diff --git a/packages/react-router/__tests__/generatePath-test.tsx b/packages/react-router/__tests__/generatePath-test.tsx
index c0bad0d374..de9fa4ee74 100644
--- a/packages/react-router/__tests__/generatePath-test.tsx
+++ b/packages/react-router/__tests__/generatePath-test.tsx
@@ -141,6 +141,28 @@ describe("generatePath", () => {
});
});
+ describe("param encoding", () => {
+ it("encodes characters that would change the URL structure", () => {
+ expect(generatePath("/courses/:id", { id: "a b?c#d%e" })).toBe(
+ "/courses/a%20b%3Fc%23d%25e",
+ );
+ expect(generatePath("/courses/:id", { id: "café…" })).toBe(
+ "/courses/caf%C3%A9%E2%80%A6",
+ );
+ });
+
+ it("preserves characters RFC 3986 allows literally in a path segment", () => {
+ // pchar sub-delims plus ":" and "@" — see RFC 3986 §3.3
+ expect(generatePath("/courses/:id", { id: "$&+,;=:@" })).toBe(
+ "/courses/$&+,;=:@",
+ );
+ // e.g. a semver build suffix survives untouched
+ expect(generatePath("/releases/:version", { version: "1.0.0+1" })).toBe(
+ "/releases/1.0.0+1",
+ );
+ });
+ });
+
it("throws only on missing named parameters, but not missing splat params", () => {
expect(() => generatePath(":foo")).toThrow();
expect(() => generatePath("/:foo")).toThrow();
diff --git a/packages/react-router/__tests__/href-test.ts b/packages/react-router/__tests__/href-test.ts
index 50d631ec93..4c06e1003f 100644
--- a/packages/react-router/__tests__/href-test.ts
+++ b/packages/react-router/__tests__/href-test.ts
@@ -52,8 +52,21 @@ describe("href", () => {
expect(href("/products/:id", { id: "abc#frag" })).toBe(
"/products/abc%23frag",
);
+ // "?" is escaped (it would start the query string), "=" is not (it is a
+ // valid pchar in a path segment, unlike in a query string)
expect(href("/products/:id", { id: "abc?x=1" })).toBe(
- "/products/abc%3Fx%3D1",
+ "/products/abc%3Fx=1",
+ );
+ });
+
+ it("preserves characters RFC 3986 allows literally in a path segment", () => {
+ // pchar sub-delims plus ":" and "@" — see RFC 3986 §3.3
+ expect(href("/products/:id", { id: "$&+,;=:@" })).toBe(
+ "/products/$&+,;=:@",
+ );
+ // e.g. a semver build suffix survives untouched
+ expect(href("/releases/:version", { version: "1.0.0+1" })).toBe(
+ "/releases/1.0.0+1",
);
});
@@ -61,11 +74,21 @@ describe("href", () => {
expect(href("/:param/*", { param: "a?b/c#d", "*": "e?f/g#h" })).toBe(
"/a%3Fb%2Fc%23d/e%3Ff/g%23h",
);
+ expect(href("/releases/*", { "*": "v1/1.0.0+1" })).toBe(
+ "/releases/v1/1.0.0+1",
+ );
});
it("round-trips through matchPath for param values with special characters", () => {
let pattern = "/products/:id";
- for (let id of ["shoes/2026-summer", "abc#frag", "abc?x=1", "a b"]) {
+ for (let id of [
+ "shoes/2026-summer",
+ "abc#frag",
+ "abc?x=1",
+ "a b",
+ "$&+,;=:@",
+ "1.0.0+1",
+ ]) {
let result = href(pattern, { id });
// before the fix, href()'s own output didn't match its own pattern
let match = matchPath(pattern, result);
diff --git a/packages/react-router/lib/href.ts b/packages/react-router/lib/href.ts
index ee82c6d743..d295e82ee1 100644
--- a/packages/react-router/lib/href.ts
+++ b/packages/react-router/lib/href.ts
@@ -1,3 +1,4 @@
+import { encodePathParam } from "./router/utils";
import type { Pages } from "./types/register";
import type { Equal } from "./types/utils";
@@ -17,14 +18,30 @@ function stringify(p: any) {
}
/**
- Returns a resolved URL path for the specified route.
-
- ```tsx
- const h = href("/:lang?/about", { lang: "en" })
- // -> `/en/about`
-
-
- ```
+ * Returns a resolved URL path for the specified route.
+ *
+ * Param values are percent-encoded for use in a path segment: characters that
+ * would change the URL structure (`/`, `?`, `#`, `%`, whitespace, non-ASCII)
+ * are escaped, while characters that RFC 3986 allows literally in a path
+ * segment (`$ & + , ; = : @`) are kept as-is. Note this differs from query-string
+ * encoding (`encodeURIComponent`/`URLSearchParams`), where those characters are
+ * delimiters and must be escaped. Splat (`*`) values are encoded per segment,
+ * preserving `/` separators.
+ *
+ * See [RFC 3986 §3.3](https://datatracker.ietf.org/doc/html/rfc3986#section-3.3)
+ *
+ * @example
+ * const h = href("/:lang?/about", { lang: "en" })
+ * // -> `/en/about`
+ *
+ *
+ *
+ * @public
+ * @category Utils
+ * @mode framework
+ * @param path The route path to resolve
+ * @param args The route params to use when resolving the path
+ * @returns The resolved URL path
*/
export function href(
path: Path,
@@ -42,7 +59,7 @@ export function href(
`Path '${path}' requires param '${param}' but it was not provided`,
);
}
- return value == null ? "" : "/" + encodeURIComponent(stringify(value));
+ return value == null ? "" : "/" + encodePathParam(stringify(value));
},
);
@@ -53,7 +70,7 @@ export function href(
const value = params?.["*"];
if (value !== undefined) {
result +=
- "/" + stringify(value).split("/").map(encodeURIComponent).join("/");
+ "/" + stringify(value).split("/").map(encodePathParam).join("/");
}
}
diff --git a/packages/react-router/lib/router/utils.ts b/packages/react-router/lib/router/utils.ts
index 356c429caa..28f501bbe8 100644
--- a/packages/react-router/lib/router/utils.ts
+++ b/packages/react-router/lib/router/utils.ts
@@ -1480,13 +1480,72 @@ function matchRouteBranch<
return matches;
}
+/**
+ * Characters that `encodeURIComponent` escapes but that are valid literally in
+ * a URL path segment. Per RFC 3986 §3.3, a path segment is made of `pchar`:
+ *
+ * ```
+ * pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
+ * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
+ * ```
+ *
+ * `encodeURIComponent` targets query-string values, where `$ & + , ; = : @`
+ * are delimiters and must be escaped — but in a path segment they carry no
+ * special meaning, and browsers keep them literal in `location.pathname`.
+ * (`! ' ( ) *` and the unreserved set are already left alone by
+ * `encodeURIComponent`, so they need no restoring.)
+ */
+const PATH_PARAM_OVERESCAPED: Record = {
+ "%24": "$",
+ "%26": "&",
+ "%2B": "+",
+ "%2C": ",",
+ "%3A": ":",
+ "%3B": ";",
+ "%3D": "=",
+ "%40": "@",
+};
+
+/**
+ * Encodes a param value for interpolation into a single URL path segment.
+ *
+ * Escapes characters that would break the path (`/ ? # %`, whitespace,
+ * non-ASCII, …) while leaving characters that RFC 3986 permits literally in a
+ * path segment untouched. Escaping those would needlessly rewrite URLs — e.g.
+ * a semver build param `1.0.0+1` would become `1.0.0%2B1` even though browsers
+ * display and match the `+` literally in `location.pathname`.
+ *
+ * See [RFC 3986 §3.3](https://datatracker.ietf.org/doc/html/rfc3986#section-3.3))
+ *
+ * @param value The param value to encode.
+ * @returns The encoded value, safe for use as a single path segment.
+ */
+export function encodePathParam(value: string): string {
+ return encodeURIComponent(value).replace(
+ /%(?:24|26|2B|2C|3A|3B|3D|40)/g,
+ (match) => PATH_PARAM_OVERESCAPED[match],
+ );
+}
+
/**
* Returns a path with params interpolated.
*
+ * Param values are percent-encoded for use in a path segment: characters that
+ * would change the URL structure (`/`, `?`, `#`, `%`, whitespace, non-ASCII)
+ * are escaped, while characters that RFC 3986 allows literally in a path
+ * segment (`$ & + , ; = : @`) are kept as-is. Note this differs from query-string
+ * encoding (`encodeURIComponent`/`URLSearchParams`), where those characters are
+ * delimiters and must be escaped. Splat (`*`) values are encoded per segment,
+ * preserving `/` separators.
+ *
+ * See [RFC 3986 §3.3](https://datatracker.ietf.org/doc/html/rfc3986#section-3.3)
+ *
* @example
* import { generatePath } from "react-router";
*
* generatePath("/users/:id", { id: "123" }); // "/users/123"
+ * generatePath("/files/:name", { name: "a b" }); // "/files/a%20b"
+ * generatePath("/releases/:v", { v: "1.0.0+1" }); // "/releases/1.0.0+1"
*
* @public
* @category Utils
@@ -1532,7 +1591,7 @@ export function generatePath(
const [, key, optional, suffix] = keyMatch;
let param = params[key as keyof typeof params];
invariant(optional === "?" || param != null, `Missing ":${key}" param`);
- return encodeURIComponent(stringify(param)) + suffix;
+ return encodePathParam(stringify(param)) + suffix;
}
// Remove any optional markers from optional static segments
From f6b681c24542b5066e2b133c2ce493b01387e360 Mon Sep 17 00:00:00 2001
From: Remix Run Bot
Date: Tue, 14 Jul 2026 15:19:15 +0000
Subject: [PATCH 3/4] chore: generate markdown docs from jsdocs
---
docs/api/utils/generatePath.md | 12 +++++++++
docs/api/utils/href.md | 48 +++++++++++++++++++++++++++++++++-
2 files changed, 59 insertions(+), 1 deletion(-)
diff --git a/docs/api/utils/generatePath.md b/docs/api/utils/generatePath.md
index 70e46c4597..0bc46bab31 100644
--- a/docs/api/utils/generatePath.md
+++ b/docs/api/utils/generatePath.md
@@ -24,10 +24,22 @@ https://github.com/remix-run/react-router/blob/main/packages/react-router/lib/ro
Returns a path with params interpolated.
+Param values are percent-encoded for use in a path segment: characters that
+would change the URL structure (`/`, `?`, `#`, `%`, whitespace, non-ASCII)
+are escaped, while characters that RFC 3986 allows literally in a path
+segment (`$ & + , ; = : @`) are kept as-is. Note this differs from query-string
+encoding (`encodeURIComponent`/`URLSearchParams`), where those characters are
+delimiters and must be escaped. Splat (`*`) values are encoded per segment,
+preserving `/` separators.
+
+See [RFC 3986 §3.3](https://datatracker.ietf.org/doc/html/rfc3986#section-3.3)
+
```tsx
import { generatePath } from "react-router";
generatePath("/users/:id", { id: "123" }); // "/users/123"
+generatePath("/files/:name", { name: "a b" }); // "/files/a%20b"
+generatePath("/releases/:v", { v: "1.0.0+1" }); // "/releases/1.0.0+1"
```
## Signature
diff --git a/docs/api/utils/href.md b/docs/api/utils/href.md
index 031d0abbf0..2d92485dbd 100644
--- a/docs/api/utils/href.md
+++ b/docs/api/utils/href.md
@@ -4,17 +4,63 @@ title: href
# href
+
+
[MODES: framework]
## Summary
-[Reference Documentation ↗](https://api.reactrouter.com/v7/functions/react-router.href.html)
+[Reference Documentation ↗](https://api.reactrouter.com/v8/functions/react-router.href.html)
Returns a resolved URL path for the specified route.
+Param values are percent-encoded for use in a path segment: characters that
+would change the URL structure (`/`, `?`, `#`, `%`, whitespace, non-ASCII)
+are escaped, while characters that RFC 3986 allows literally in a path
+segment (`$ & + , ; = : @`) are kept as-is. Note this differs from query-string
+encoding (`encodeURIComponent`/`URLSearchParams`), where those characters are
+delimiters and must be escaped. Splat (`*`) values are encoded per segment,
+preserving `/` separators.
+
+See [RFC 3986 §3.3](https://datatracker.ietf.org/doc/html/rfc3986#section-3.3)
+
```tsx
const h = href("/:lang?/about", { lang: "en" })
// -> `/en/about`
```
+
+## Signature
+
+```tsx
+function href(
+ path: Path,
+ ...args: Args[Path]
+): string
+```
+
+## Params
+
+### path
+
+The route path to resolve
+
+### args
+
+The route params to use when resolving the path
+
+## Returns
+
+The resolved URL path
+
From f75c89fd9cf76177c22d008265d78ee9184c483e Mon Sep 17 00:00:00 2001
From: Matt Brophy
Date: Tue, 14 Jul 2026 13:23:54 -0400
Subject: [PATCH 4/4] Update docs links to v8 API reference (#15316)
* Update docs links to v8 API reference
* Generate utility docs from JSDoc
* Remove hidden docs generation
---
docs/api/data-routers/createStaticRouter.md | 4 +-
.../react-router.config.ts.md | 2 +-
docs/api/framework-conventions/routes.ts.md | 12 ++---
docs/api/hooks/useFetcher.md | 2 +-
docs/api/hooks/useFormAction.md | 4 +-
docs/api/hooks/useHref.md | 4 +-
docs/api/hooks/useLinkClickHandler.md | 4 +-
docs/api/hooks/useResolvedPath.md | 4 +-
docs/api/hooks/useViewTransitionState.md | 4 +-
docs/api/other-api/adapter.md | 8 ++--
docs/api/utils/IsCookieFunction.md | 35 +++++++++++++-
docs/api/utils/IsSessionFunction.md | 35 +++++++++++++-
docs/api/utils/createCookie.md | 29 ++++++++++-
docs/api/utils/createCookieSessionStorage.md | 34 ++++++++++++-
docs/api/utils/createMemorySessionStorage.md | 40 ++++++++++++++--
docs/api/utils/createPath.md | 29 +++++++++--
docs/api/utils/createRequestHandler.md | 12 -----
docs/api/utils/createRoutesStub.md | 36 +++++++++++---
docs/api/utils/createSearchParams.md | 42 ++++++++++------
docs/api/utils/createSession.md | 17 -------
docs/api/utils/createSessionStorage.md | 17 -------
docs/api/utils/generatePath.md | 4 +-
docs/api/utils/isCookie.md | 28 ++++++++++-
docs/api/utils/isSession.md | 28 ++++++++++-
docs/api/utils/parsePath.md | 23 +++++++--
docs/explanation/sessions-and-cookies.md | 24 +++++-----
docs/explanation/state-management.md | 4 +-
docs/how-to/presets.md | 4 +-
docs/how-to/server-bundles.md | 4 +-
docs/start/data/route-object.md | 4 +-
docs/start/data/routing.md | 2 +-
docs/start/framework/pending-ui.md | 2 +-
docs/start/framework/route-module.md | 16 +++----
docs/start/framework/routing.md | 2 +-
docs/tutorials/address-book.md | 20 ++++----
docs/tutorials/quickstart.md | 2 +-
packages/react-router/lib/dom/dom.ts | 48 +++++++++----------
.../lib/dom/ssr/routes-test-stub.tsx | 13 +++++
packages/react-router/lib/router/history.ts | 6 +++
.../lib/server-runtime/cookies.ts | 30 +++++++++++-
.../react-router/lib/server-runtime/server.ts | 12 +++++
.../lib/server-runtime/sessions.ts | 33 ++++++++++++-
.../server-runtime/sessions/cookieStorage.ts | 8 ++++
.../server-runtime/sessions/memoryStorage.ts | 7 +++
scripts/docs.ts | 23 ++++++++-
45 files changed, 534 insertions(+), 187 deletions(-)
delete mode 100644 docs/api/utils/createRequestHandler.md
delete mode 100644 docs/api/utils/createSession.md
delete mode 100644 docs/api/utils/createSessionStorage.md
diff --git a/docs/api/data-routers/createStaticRouter.md b/docs/api/data-routers/createStaticRouter.md
index c7355f3921..ff89645598 100644
--- a/docs/api/data-routers/createStaticRouter.md
+++ b/docs/api/data-routers/createStaticRouter.md
@@ -50,8 +50,8 @@ function createStaticRouter(
opts: {
branches?: RouteBranch[];
future?: Partial;
- } = ,
-): DataRouter {}
+ } = {},
+): DataRouter
```
## Params
diff --git a/docs/api/framework-conventions/react-router.config.ts.md b/docs/api/framework-conventions/react-router.config.ts.md
index 58b601ab63..4021b2216c 100644
--- a/docs/api/framework-conventions/react-router.config.ts.md
+++ b/docs/api/framework-conventions/react-router.config.ts.md
@@ -13,7 +13,7 @@ order: 3
This file is optional
-[Reference Documentation ↗](https://api.reactrouter.com/v7/types/_react-router_dev.config.Config.html)
+[Reference Documentation ↗](https://api.reactrouter.com/v8/types/_react-router_dev.config.Config.html)
React Router framework configuration file that lets you customize aspects of your React Router application like server-side rendering, directory locations, and build settings.
diff --git a/docs/api/framework-conventions/routes.ts.md b/docs/api/framework-conventions/routes.ts.md
index 94ba02eef9..b452ddf3b3 100644
--- a/docs/api/framework-conventions/routes.ts.md
+++ b/docs/api/framework-conventions/routes.ts.md
@@ -13,7 +13,7 @@ order: 2
This file is required
-[Reference Documentation ↗](https://api.reactrouter.com/v7/interfaces/_react-router_dev.routes.RouteConfigEntry.html)
+[Reference Documentation ↗](https://api.reactrouter.com/v8/interfaces/_react-router_dev.routes.RouteConfigEntry.html)
Configuration file that maps URL patterns to route modules in your application.
@@ -59,9 +59,9 @@ export default flatRoutes() satisfies RouteConfig;
### Route Helpers
[routing]: ../../start/framework/routing
-[route]: https://api.reactrouter.com/v7/functions/_react-router_dev.routes.route.html
-[index]: https://api.reactrouter.com/v7/functions/_react-router_dev.routes.index.html
-[layout]: https://api.reactrouter.com/v7/functions/_react-router_dev.routes.layout.html
-[prefix]: https://api.reactrouter.com/v7/functions/_react-router_dev.routes.prefix.html
-[relative]: https://api.reactrouter.com/v7/functions/_react-router_dev.routes.relative.html
+[route]: https://api.reactrouter.com/v8/functions/_react-router_dev.routes.route.html
+[index]: https://api.reactrouter.com/v8/functions/_react-router_dev.routes.index.html
+[layout]: https://api.reactrouter.com/v8/functions/_react-router_dev.routes.layout.html
+[prefix]: https://api.reactrouter.com/v8/functions/_react-router_dev.routes.prefix.html
+[relative]: https://api.reactrouter.com/v8/functions/_react-router_dev.routes.relative.html
[file-route-conventions]: ../../how-to/file-route-conventions
diff --git a/docs/api/hooks/useFetcher.md b/docs/api/hooks/useFetcher.md
index d70bf01543..c956ba1223 100644
--- a/docs/api/hooks/useFetcher.md
+++ b/docs/api/hooks/useFetcher.md
@@ -64,7 +64,7 @@ function useFetcher({
key,
}: {
key?: string;
-} = ): FetcherWithComponents> {}
+} = {}): FetcherWithComponents>
```
## Params
diff --git a/docs/api/hooks/useFormAction.md b/docs/api/hooks/useFormAction.md
index 70f306db52..32e1830fb2 100644
--- a/docs/api/hooks/useFormAction.md
+++ b/docs/api/hooks/useFormAction.md
@@ -55,8 +55,8 @@ function useFormAction(
relative,
}: {
relative?: RelativeRoutingType;
- } = ,
-): string {}
+ } = {},
+): string
```
## Params
diff --git a/docs/api/hooks/useHref.md b/docs/api/hooks/useHref.md
index bebe1a2378..a99a626e59 100644
--- a/docs/api/hooks/useHref.md
+++ b/docs/api/hooks/useHref.md
@@ -42,8 +42,8 @@ function useHref(
relative,
}: {
relative?: RelativeRoutingType;
- } = ,
-): string {}
+ } = {},
+): string
```
## Params
diff --git a/docs/api/hooks/useLinkClickHandler.md b/docs/api/hooks/useLinkClickHandler.md
index 6f7a7a019d..a484f7682a 100644
--- a/docs/api/hooks/useLinkClickHandler.md
+++ b/docs/api/hooks/useLinkClickHandler.md
@@ -51,8 +51,8 @@ function useLinkClickHandler(
viewTransition?: boolean;
defaultShouldRevalidate?: boolean;
useTransitions?: boolean;
- } = ,
-): (event: React.MouseEvent) => void {}
+ } = {},
+): (event: React.MouseEvent) => void
```
## Params
diff --git a/docs/api/hooks/useResolvedPath.md b/docs/api/hooks/useResolvedPath.md
index dd1cb54c69..07665b8eaa 100644
--- a/docs/api/hooks/useResolvedPath.md
+++ b/docs/api/hooks/useResolvedPath.md
@@ -47,8 +47,8 @@ function useResolvedPath(
relative,
}: {
relative?: RelativeRoutingType;
- } = ,
-): Path {}
+ } = {},
+): Path
```
## Params
diff --git a/docs/api/hooks/useViewTransitionState.md b/docs/api/hooks/useViewTransitionState.md
index 8fd50bb5f6..766feb5762 100644
--- a/docs/api/hooks/useViewTransitionState.md
+++ b/docs/api/hooks/useViewTransitionState.md
@@ -38,8 +38,8 @@ function useViewTransitionState(
relative,
}: {
relative?: RelativeRoutingType;
- } = ,
-) {}
+ } = {},
+)
```
## Params
diff --git a/docs/api/other-api/adapter.md b/docs/api/other-api/adapter.md
index 5a7251a118..6de19c9241 100644
--- a/docs/api/other-api/adapter.md
+++ b/docs/api/other-api/adapter.md
@@ -22,7 +22,7 @@ Each adapter has the same API. Some adapters also have options specific to the p
## `@react-router/express`
-[Reference Documentation ↗](https://api.reactrouter.com/v7/modules/_react-router_express.html)
+[Reference Documentation ↗](https://api.reactrouter.com/v8/modules/_react-router_express.html)
Here's an example with [Express][express]:
@@ -124,7 +124,7 @@ Make sure that `--conditions development` is included in the `dev` script so tha
## `@react-router/architect`
-[Reference Documentation ↗](https://api.reactrouter.com/v7/modules/_react-router_architect.html)
+[Reference Documentation ↗](https://api.reactrouter.com/v8/modules/_react-router_architect.html)
Here's an example with Architect:
@@ -139,7 +139,7 @@ export const handler = createRequestHandler({
## `@react-router/cloudflare`
-[Reference Documentation ↗](https://api.reactrouter.com/v7/modules/_react-router_cloudflare.html)
+[Reference Documentation ↗](https://api.reactrouter.com/v8/modules/_react-router_cloudflare.html)
Here's an example with Cloudflare:
@@ -173,7 +173,7 @@ export default {
While not a direct "adapter" like the above, this package contains utilities for working with Node-based adapters.
-[Reference Documentation ↗](https://api.reactrouter.com/v7/modules/_react-router_node.html)
+[Reference Documentation ↗](https://api.reactrouter.com/v8/modules/_react-router_node.html)
### Node Version Support
diff --git a/docs/api/utils/IsCookieFunction.md b/docs/api/utils/IsCookieFunction.md
index 5157a6d164..af2589e566 100644
--- a/docs/api/utils/IsCookieFunction.md
+++ b/docs/api/utils/IsCookieFunction.md
@@ -4,8 +4,41 @@ title: IsCookieFunction
# IsCookieFunction
+
+
[MODES: framework, data]
## Summary
-[Reference Documentation ↗](https://api.reactrouter.com/v7/functions/react-router.IsCookieFunction.html)
+[Reference Documentation ↗](https://api.reactrouter.com/v8/types/react-router.IsCookieFunction.html)
+
+A function that determines whether a value is a React Router [`Cookie`](https://api.reactrouter.com/v8/interfaces/react-router.Cookie.html)
+object.
+
+## Signature
+
+```tsx
+type IsCookieFunction = (object: any) => object is Cookie;
+```
+
+## Params
+
+### object
+
+The value to check.
+
+## Returns
+
+`true` if the value is a React Router [`Cookie`](https://api.reactrouter.com/v8/interfaces/react-router.Cookie.html) object;
+otherwise, `false`.
+
diff --git a/docs/api/utils/IsSessionFunction.md b/docs/api/utils/IsSessionFunction.md
index bf3321cfe5..fde9cb9654 100644
--- a/docs/api/utils/IsSessionFunction.md
+++ b/docs/api/utils/IsSessionFunction.md
@@ -4,8 +4,41 @@ title: IsSessionFunction
# IsSessionFunction
+
+
[MODES: framework, data]
## Summary
-[Reference Documentation ↗](https://api.reactrouter.com/v7/functions/react-router.IsSessionFunction.html)
+[Reference Documentation ↗](https://api.reactrouter.com/v8/types/react-router.IsSessionFunction.html)
+
+A function that determines whether a value is a React Router [`Session`](https://api.reactrouter.com/v8/interfaces/react-router.Session.html)
+object.
+
+## Signature
+
+```tsx
+type IsSessionFunction = (object: any) => object is Session;
+```
+
+## Params
+
+### object
+
+The value to check.
+
+## Returns
+
+`true` if the value is a React Router [`Session`](https://api.reactrouter.com/v8/interfaces/react-router.Session.html) object;
+otherwise, `false`.
+
diff --git a/docs/api/utils/createCookie.md b/docs/api/utils/createCookie.md
index 593dd558d9..66fa3100df 100644
--- a/docs/api/utils/createCookie.md
+++ b/docs/api/utils/createCookie.md
@@ -4,10 +4,37 @@ title: createCookie
# createCookie
+
+
[MODES: framework, data]
## Summary
-[Reference Documentation ↗](https://api.reactrouter.com/v7/functions/react-router.createCookie.html)
+[Reference Documentation ↗](https://api.reactrouter.com/v8/functions/react-router.createCookie.html)
Creates a logical container for managing a browser cookie from the server.
+
+## Params
+
+### name
+
+The name of the cookie.
+
+### cookieOptions
+
+Options for parsing and serializing the cookie.
+
+## Returns
+
+A [`Cookie`](https://api.reactrouter.com/v8/interfaces/react-router.Cookie.html) object for parsing and serializing the cookie.
+
diff --git a/docs/api/utils/createCookieSessionStorage.md b/docs/api/utils/createCookieSessionStorage.md
index 83828fd1f4..78d5c2a93d 100644
--- a/docs/api/utils/createCookieSessionStorage.md
+++ b/docs/api/utils/createCookieSessionStorage.md
@@ -4,11 +4,23 @@ title: createCookieSessionStorage
# createCookieSessionStorage
+
+
[MODES: framework, data]
## Summary
-[Reference Documentation ↗](https://api.reactrouter.com/v7/functions/react-router.createCookieSessionStorage.html)
+[Reference Documentation ↗](https://api.reactrouter.com/v8/functions/react-router.createCookieSessionStorage.html)
Creates and returns a SessionStorage object that stores all session data
directly in the session cookie itself.
@@ -17,3 +29,23 @@ This has the advantage that no database or other backend services are
needed, and can help to simplify some load-balanced scenarios. However, it
also has the limitation that serialized session data may not exceed the
browser's maximum cookie size. Trade-offs!
+
+## Signature
+
+```tsx
+function createCookieSessionStorage({
+ cookie: cookieArg,
+}: CookieSessionStorageOptions = {}): SessionStorage
+```
+
+## Params
+
+### options
+
+Options for creating the cookie-backed session storage.
+
+## Returns
+
+A [`SessionStorage`](https://api.reactrouter.com/v8/interfaces/react-router.SessionStorage.html) object that stores all session data in its
+cookie.
+
diff --git a/docs/api/utils/createMemorySessionStorage.md b/docs/api/utils/createMemorySessionStorage.md
index 8d916894da..53cdb372f3 100644
--- a/docs/api/utils/createMemorySessionStorage.md
+++ b/docs/api/utils/createMemorySessionStorage.md
@@ -4,14 +4,44 @@ title: createMemorySessionStorage
# createMemorySessionStorage
+
+
[MODES: framework, data]
## Summary
-[Reference Documentation ↗](https://api.reactrouter.com/v7/functions/react-router.createMemorySessionStorage.html)
+[Reference Documentation ↗](https://api.reactrouter.com/v8/functions/react-router.createMemorySessionStorage.html)
+
+Creates and returns a simple in-memory SessionStorage object.
+
+Intended for local development and testing. It does not scale beyond a single
+process, and all session data is lost when the server process stops/restarts.
+
+## Signature
+
+```tsx
+function createMemorySessionStorage({
+ cookie,
+}: MemorySessionStorageOptions = {}): SessionStorage
+```
+
+## Params
+
+### options
+
+Options for creating the in-memory session storage.
+
+## Returns
-Creates and returns a simple in-memory SessionStorage object, mostly useful
-for testing and as a reference implementation.
+A [`SessionStorage`](https://api.reactrouter.com/v8/interfaces/react-router.SessionStorage.html) object that stores session data in memory.
-Note: This storage does not scale beyond a single process, so it is not
-suitable for most production scenarios.
diff --git a/docs/api/utils/createPath.md b/docs/api/utils/createPath.md
index 195141563d..e566a8287d 100644
--- a/docs/api/utils/createPath.md
+++ b/docs/api/utils/createPath.md
@@ -4,24 +4,43 @@ title: createPath
# createPath
+
+
[MODES: framework, data, declarative]
## Summary
-[Reference Documentation ↗](https://api.reactrouter.com/v7/functions/react-router.createPath.html)
+[Reference Documentation ↗](https://api.reactrouter.com/v8/functions/react-router.createPath.html)
Creates a string URL path from the given pathname, search, and hash components.
## Signature
```tsx
-createPath(__namedParameters): string
+function createPath({
+ pathname = "/",
+ search = "",
+ hash = "",
+}: Partial)
```
## Params
-### \_\_namedParameters
+### path
+
+The pathname, search, and hash components to combine.
+
+## Returns
-[modes: framework, data, declarative]
+The combined URL path.
-_No documentation_
diff --git a/docs/api/utils/createRequestHandler.md b/docs/api/utils/createRequestHandler.md
deleted file mode 100644
index b85ba28ec5..0000000000
--- a/docs/api/utils/createRequestHandler.md
+++ /dev/null
@@ -1,12 +0,0 @@
----
-title: createRequestHandler
-hidden: true
----
-
-# createRequestHandler
-
-[MODES: framework, data, declarative]
-
-## Summary
-
-[Reference Documentation ↗](https://api.reactrouter.com/v7/functions/react-router.createRequestHandler.html)
diff --git a/docs/api/utils/createRoutesStub.md b/docs/api/utils/createRoutesStub.md
index e707fb6555..4d11d903cd 100644
--- a/docs/api/utils/createRoutesStub.md
+++ b/docs/api/utils/createRoutesStub.md
@@ -4,28 +4,50 @@ title: createRoutesStub
# createRoutesStub
+
+
[MODES: framework, data]
## Summary
-[Reference Documentation ↗](https://api.reactrouter.com/v7/functions/react-router.createRoutesStub.html)
+[Reference Documentation ↗](https://api.reactrouter.com/v8/functions/react-router.createRoutesStub.html)
+
+Creates a React component that renders the provided routes in a test-friendly
+React Router context.
+
+Use this to unit test components that rely on router context, such as
+`loaderData`, `actionData`, and route matches.
## Signature
```tsx
-createRoutesStub(routes, context): undefined
+function createRoutesStub(
+ routes: StubRouteObject[],
+ _context?: RouterContextProvider,
+)
```
## Params
### routes
-[modes: framework, data]
+The route objects to render in the test router.
+
+### _context
-_No documentation_
+An optional [`RouterContextProvider`](../utils/RouterContextProvider) for supplying application context values to route middleware, loaders, and actions.
-### context
+## Returns
-[modes: framework, data]
+A React component that renders the test router.
-_No documentation_
diff --git a/docs/api/utils/createSearchParams.md b/docs/api/utils/createSearchParams.md
index b0603e8f5e..18ff59d1c8 100644
--- a/docs/api/utils/createSearchParams.md
+++ b/docs/api/utils/createSearchParams.md
@@ -4,46 +4,58 @@ title: createSearchParams
# createSearchParams
+
+
[MODES: framework, data, declarative]
## Summary
-[Reference Documentation ↗](https://api.reactrouter.com/v7/functions/react-router.createSearchParams.html)
+[Reference Documentation ↗](https://api.reactrouter.com/v8/functions/react-router.createSearchParams.html)
Creates a URLSearchParams object using the given initializer.
-This is identical to `new URLSearchParams(init)` except it also
-supports arrays as values in the object form of the initializer
-instead of just strings. This is convenient when you need multiple
-values for a given key, but don't want to use an array initializer.
-
-For example, instead of:
+This is identical to `new URLSearchParams(init)` except it also supports
+arrays as values in the object form of the initializer instead of just
+strings. This is convenient when you need multiple values for a given key,
+but don't want to use an array initializer.
```tsx
+// Instead of:
let searchParams = new URLSearchParams([
["sort", "name"],
["sort", "price"],
]);
-```
-
-you can do:
-```
+// You can do:
let searchParams = createSearchParams({
- sort: ['name', 'price']
+ sort: ["name", "price"],
});
```
## Signature
```tsx
-createSearchParams(init): URLSearchParams
+function createSearchParams(init: URLSearchParamsInit = ""): URLSearchParams
```
## Params
### init
-[modes: framework, data, declarative]
+The value used to initialize the URL search parameters.
+
+## Returns
+
+A URLSearchParams object containing the initialized search
+parameters.
-_No documentation_
diff --git a/docs/api/utils/createSession.md b/docs/api/utils/createSession.md
deleted file mode 100644
index 37d738b705..0000000000
--- a/docs/api/utils/createSession.md
+++ /dev/null
@@ -1,17 +0,0 @@
----
-title: createSession
-hidden: true
----
-
-# createSession
-
-[MODES: framework, data, declarative]
-
-## Summary
-
-[Reference Documentation ↗](https://api.reactrouter.com/v7/functions/react-router.createSession.html)
-
-Creates a new Session object.
-
-Note: This function is typically not invoked directly by application code.
-Instead, use a `SessionStorage` object's `getSession` method.
diff --git a/docs/api/utils/createSessionStorage.md b/docs/api/utils/createSessionStorage.md
deleted file mode 100644
index 29a1b62352..0000000000
--- a/docs/api/utils/createSessionStorage.md
+++ /dev/null
@@ -1,17 +0,0 @@
----
-title: createSessionStorage
-hidden: true
----
-
-# createSessionStorage
-
-[MODES: framework, data, declarative]
-
-## Summary
-
-[Reference Documentation ↗](https://api.reactrouter.com/v7/functions/react-router.createSessionStorage.html)
-
-Creates a SessionStorage object using a SessionIdStorageStrategy.
-
-Note: This is a low-level API that should only be used if none of the
-existing session storage options meet your requirements.
diff --git a/docs/api/utils/generatePath.md b/docs/api/utils/generatePath.md
index 0bc46bab31..dc70034e1f 100644
--- a/docs/api/utils/generatePath.md
+++ b/docs/api/utils/generatePath.md
@@ -47,8 +47,8 @@ generatePath("/releases/:v", { v: "1.0.0+1" }); // "/releases/1.0.0+1"
```tsx
function generatePath(
originalPath: Path,
- params: GeneratePathParams = as any,
-): string {}
+ params: GeneratePathParams = {} as any,
+): string
```
## Params
diff --git a/docs/api/utils/isCookie.md b/docs/api/utils/isCookie.md
index ac0f3b3f32..b74c44d2a0 100644
--- a/docs/api/utils/isCookie.md
+++ b/docs/api/utils/isCookie.md
@@ -4,10 +4,34 @@ title: isCookie
# isCookie
+
+
[MODES: framework, data]
## Summary
-[Reference Documentation ↗](https://api.reactrouter.com/v7/functions/react-router.isCookie.html)
+[Reference Documentation ↗](https://api.reactrouter.com/v8/variables/react-router.isCookie.html)
+
+Returns `true` if a value is a React Router [`Cookie`](https://api.reactrouter.com/v8/interfaces/react-router.Cookie.html) object.
+
+## Params
+
+### object
+
+The value to check.
+
+## Returns
+
+`true` if the value is a React Router [`Cookie`](https://api.reactrouter.com/v8/interfaces/react-router.Cookie.html) object;
+otherwise, `false`.
-Returns true if an object is a Remix cookie container.
diff --git a/docs/api/utils/isSession.md b/docs/api/utils/isSession.md
index ebac237abc..9842a116ca 100644
--- a/docs/api/utils/isSession.md
+++ b/docs/api/utils/isSession.md
@@ -4,10 +4,34 @@ title: isSession
# isSession
+
+
[MODES: framework, data]
## Summary
-[Reference Documentation ↗](https://api.reactrouter.com/v7/functions/react-router.isSession.html)
+[Reference Documentation ↗](https://api.reactrouter.com/v8/variables/react-router.isSession.html)
+
+Returns `true` if a value is a React Router [`Session`](https://api.reactrouter.com/v8/interfaces/react-router.Session.html) object.
+
+## Params
+
+### object
+
+The value to check.
+
+## Returns
+
+`true` if the value is a React Router [`Session`](https://api.reactrouter.com/v8/interfaces/react-router.Session.html) object;
+otherwise, `false`.
-Returns true if an object is a React Router session.
diff --git a/docs/api/utils/parsePath.md b/docs/api/utils/parsePath.md
index bb1c485cfe..1cb7aa4a68 100644
--- a/docs/api/utils/parsePath.md
+++ b/docs/api/utils/parsePath.md
@@ -4,24 +4,39 @@ title: parsePath
# parsePath
+
+
[MODES: framework, data, declarative]
## Summary
-[Reference Documentation ↗](https://api.reactrouter.com/v7/functions/react-router.parsePath.html)
+[Reference Documentation ↗](https://api.reactrouter.com/v8/functions/react-router.parsePath.html)
Parses a string URL path into its separate pathname, search, and hash components.
## Signature
```tsx
-parsePath(path): Partial
+function parsePath(path: string): Partial
```
## Params
### path
-[modes: framework, data, declarative]
+The URL path to parse.
+
+## Returns
+
+The parsed pathname, search, and hash components.
-_No documentation_
diff --git a/docs/explanation/sessions-and-cookies.md b/docs/explanation/sessions-and-cookies.md
index dacf9df18a..5cd685deb5 100644
--- a/docs/explanation/sessions-and-cookies.md
+++ b/docs/explanation/sessions-and-cookies.md
@@ -449,17 +449,17 @@ To learn more about each attribute, please see the [MDN Set-Cookie docs][cookie-
[csrf]: https://developer.mozilla.org/en-US/docs/Glossary/CSRF
[cookies]: #cookies
[sessions]: #sessions
-[session-storage]: https://api.reactrouter.com/v7/interfaces/react-router.SessionStorage
-[session-api]: https://api.reactrouter.com/v7/interfaces/react-router.Session
-[is-session]: https://api.reactrouter.com/v7/functions/react-router.isSession
-[cookie-api]: https://api.reactrouter.com/v7/interfaces/react-router.Cookie
-[create-session-storage]: https://api.reactrouter.com/v7/functions/react-router.createSessionStorage
-[create-session]: https://api.reactrouter.com/v7/functions/react-router.createSession
-[create-memory-session-storage]: https://api.reactrouter.com/v7/functions/react-router.createMemorySessionStorage
-[create-file-session-storage]: https://api.reactrouter.com/v7/functions/_react-router_node.createFileSessionStorage
-[create-workers-kv-session-storage]: https://api.reactrouter.com/v7/functions/_react-router_cloudflare.createWorkersKVSessionStorage
-[create-arc-table-session-storage]: https://api.reactrouter.com/v7/functions/_react-router_architect.createArcTableSessionStorage
+[session-storage]: https://api.reactrouter.com/v8/interfaces/react-router.SessionStorage
+[session-api]: https://api.reactrouter.com/v8/interfaces/react-router.Session
+[is-session]: https://api.reactrouter.com/v8/variables/react-router.isSession.html
+[cookie-api]: https://api.reactrouter.com/v8/interfaces/react-router.Cookie
+[create-session-storage]: https://api.reactrouter.com/v8/functions/react-router.createSessionStorage
+[create-session]: https://api.reactrouter.com/v8/variables/react-router.createSession.html
+[create-memory-session-storage]: https://api.reactrouter.com/v8/functions/react-router.createMemorySessionStorage
+[create-file-session-storage]: https://api.reactrouter.com/v8/functions/_react-router_node.createFileSessionStorage
+[create-workers-kv-session-storage]: https://api.reactrouter.com/v8/functions/_react-router_cloudflare.createWorkersKVSessionStorage
+[create-arc-table-session-storage]: https://api.reactrouter.com/v8/functions/_react-router_architect.createArcTableSessionStorage
[cookie]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies
[cookie-attrs]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#attributes
-[is-cookie]: https://api.reactrouter.com/v7/functions/react-router.isCookie
-[create-cookie]: https://api.reactrouter.com/v7/functions/react-router.createCookie
+[is-cookie]: https://api.reactrouter.com/v8/variables/react-router.isCookie.html
+[create-cookie]: https://api.reactrouter.com/v8/functions/react-router.createCookie
diff --git a/docs/explanation/state-management.md b/docs/explanation/state-management.md
index c2b0304e99..07943f9c3e 100644
--- a/docs/explanation/state-management.md
+++ b/docs/explanation/state-management.md
@@ -510,8 +510,8 @@ If you ever find yourself entangled in managing and synchronizing state for netw
[redux]: https://redux.js.org/
[tanstack_query]: https://tanstack.com/query/latest
[apollo]: https://www.apollographql.com/
-[use_navigation]: https://api.reactrouter.com/v7/functions/react-router.useNavigation
-[use_fetcher]: https://api.reactrouter.com/v7/functions/react-router.useFetcher
+[use_navigation]: https://api.reactrouter.com/v8/functions/react-router.useNavigation
+[use_fetcher]: https://api.reactrouter.com/v8/functions/react-router.useFetcher
[loader_data]: ../start/framework/data-loading
[action_data]: ../start/framework/actions
[cookies]: ./sessions-and-cookies#cookies
diff --git a/docs/how-to/presets.md b/docs/how-to/presets.md
index febf65418c..10145fd50a 100644
--- a/docs/how-to/presets.md
+++ b/docs/how-to/presets.md
@@ -98,6 +98,6 @@ export default {
} satisfies Config;
```
-[react-router-config]: https://api.reactrouter.com/v7/types/_react-router_dev.config.Config.html
-[preset-type]: https://api.reactrouter.com/v7/types/_react-router_dev.config.Preset.html
+[react-router-config]: https://api.reactrouter.com/v8/types/_react-router_dev.config.Config.html
+[preset-type]: https://api.reactrouter.com/v8/types/_react-router_dev.config.Preset.html
[server-bundles]: ./server-bundles
diff --git a/docs/how-to/server-bundles.md b/docs/how-to/server-bundles.md
index 7c4a3a09db..f58a437ffd 100644
--- a/docs/how-to/server-bundles.md
+++ b/docs/how-to/server-bundles.md
@@ -62,5 +62,5 @@ When using server bundles, the build manifest contains the following properties:
- `routeIdToServerBundleId` — An object that maps route IDs to their server bundle ID
- `routes` — A route manifest that maps route IDs to route metadata. This can be used to drive a custom routing layer in front of your React Router request handlers
-[react-router-config]: https://api.reactrouter.com/v7/types/_react-router_dev.config.Config.html
-[server-bundles-function]: https://api.reactrouter.com/v7/types/_react-router_dev.config.ServerBundlesFunction.html
+[react-router-config]: https://api.reactrouter.com/v8/types/_react-router_dev.config.Config.html
+[server-bundles-function]: https://api.reactrouter.com/v8/types/_react-router_dev.config.ServerBundlesFunction.html
diff --git a/docs/start/data/route-object.md b/docs/start/data/route-object.md
index 0a9592caef..b26b088719 100644
--- a/docs/start/data/route-object.md
+++ b/docs/start/data/route-object.md
@@ -216,7 +216,7 @@ createBrowserRouter([
]);
```
-[`ShouldRevalidateFunctionArgs` Reference Documentation ↗](https://api.reactrouter.com/v7/interfaces/react-router.ShouldRevalidateFunctionArgs.html)
+[`ShouldRevalidateFunctionArgs` Reference Documentation ↗](https://api.reactrouter.com/v8/interfaces/react-router.ShouldRevalidateFunctionArgs.html)
Please note the default behavior is different in [Framework Mode](../modes).
@@ -263,6 +263,6 @@ See also:
Next: [Data Loading](./data-loading)
-[loader-params]: https://api.reactrouter.com/v7/interfaces/react-router.LoaderFunctionArgs
+[loader-params]: https://api.reactrouter.com/v8/interfaces/react-router.LoaderFunctionArgs
[middleware]: ../../how-to/middleware
[use-matches]: ../../api/hooks/useMatches
diff --git a/docs/start/data/routing.md b/docs/start/data/routing.md
index 5365a14425..67f777b72e 100644
--- a/docs/start/data/routing.md
+++ b/docs/start/data/routing.md
@@ -278,4 +278,4 @@ const { "*": splat } = params;
Next: [Route Object](./route-object)
-[outlet]: https://api.reactrouter.com/v7/functions/react-router.Outlet.html
+[outlet]: https://api.reactrouter.com/v8/functions/react-router.Outlet.html
diff --git a/docs/start/framework/pending-ui.md b/docs/start/framework/pending-ui.md
index 24e107397f..5d5d949ccb 100644
--- a/docs/start/framework/pending-ui.md
+++ b/docs/start/framework/pending-ui.md
@@ -139,4 +139,4 @@ function Task({ task }) {
Next: [Testing](./testing)
-[use_fetcher]: https://api.reactrouter.com/v7/functions/react-router.useFetcher.html
+[use_fetcher]: https://api.reactrouter.com/v8/functions/react-router.useFetcher.html
diff --git a/docs/start/framework/route-module.md b/docs/start/framework/route-module.md
index fe780e6773..e2ac6206ef 100644
--- a/docs/start/framework/route-module.md
+++ b/docs/start/framework/route-module.md
@@ -500,27 +500,27 @@ export function shouldRevalidate(
When using [SPA Mode][spa-mode], there are no server loaders to call on navigations, so `shouldRevalidate` behaves the same as it does in [Data Mode][data-mode-should-revalidate].
-[`ShouldRevalidateFunctionArgs` Reference Documentation ↗](https://api.reactrouter.com/v7/interfaces/react-router.ShouldRevalidateFunctionArgs.html)
+[`ShouldRevalidateFunctionArgs` Reference Documentation ↗](https://api.reactrouter.com/v8/interfaces/react-router.ShouldRevalidateFunctionArgs.html)
---
Next: [Rendering Strategies](./rendering)
-[middleware-params]: https://api.reactrouter.com/v7/types/react-router.MiddlewareFunction.html
+[middleware-params]: https://api.reactrouter.com/v8/types/react-router.MiddlewareFunction.html
[middleware]: ../../how-to/middleware
[when-middleware-runs]: ../../how-to/middleware#when-middleware-runs
-[loader-params]: https://api.reactrouter.com/v7/interfaces/react-router.LoaderFunctionArgs
-[client-loader-params]: https://api.reactrouter.com/v7/types/react-router.ClientLoaderFunctionArgs
-[action-params]: https://api.reactrouter.com/v7/interfaces/react-router.ActionFunctionArgs
-[client-action-params]: https://api.reactrouter.com/v7/types/react-router.ClientActionFunctionArgs
+[loader-params]: https://api.reactrouter.com/v8/interfaces/react-router.LoaderFunctionArgs
+[client-loader-params]: https://api.reactrouter.com/v8/types/react-router.ClientLoaderFunctionArgs
+[action-params]: https://api.reactrouter.com/v8/interfaces/react-router.ActionFunctionArgs
+[client-action-params]: https://api.reactrouter.com/v8/types/react-router.ClientActionFunctionArgs
[use-route-error]: ../../api/hooks/useRouteError
[is-route-error-response]: ../../api/utils/isRouteErrorResponse
[headers]: https://developer.mozilla.org/en-US/docs/Web/API/Response/headers
[use-matches]: ../../api/hooks/useMatches
[link-element]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link
[meta-element]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta
-[meta-params]: https://api.reactrouter.com/v7/interfaces/react-router.MetaArgs
-[meta-function]: https://api.reactrouter.com/v7/types/react-router.MetaDescriptor.html
+[meta-params]: https://api.reactrouter.com/v8/interfaces/react-router.MetaArgs
+[meta-function]: https://api.reactrouter.com/v8/types/react-router.MetaDescriptor.html
[data-mode-should-revalidate]: ../data/route-object#shouldrevalidate
[spa-mode]: ../../how-to/spa
[client-data]: ../../how-to/client-data
diff --git a/docs/start/framework/routing.md b/docs/start/framework/routing.md
index 73845a8d63..982bbfea2a 100644
--- a/docs/start/framework/routing.md
+++ b/docs/start/framework/routing.md
@@ -359,4 +359,4 @@ Note that these routes do not participate in data loading, actions, code splitti
Next: [Route Module](./route-module)
[file-route-conventions]: ../../how-to/file-route-conventions
-[outlet]: https://api.reactrouter.com/v7/functions/react-router.Outlet.html
+[outlet]: https://api.reactrouter.com/v8/functions/react-router.Outlet.html
diff --git a/docs/tutorials/address-book.md b/docs/tutorials/address-book.md
index ac47c49926..e1417315e0 100644
--- a/docs/tutorials/address-book.md
+++ b/docs/tutorials/address-book.md
@@ -1942,10 +1942,10 @@ That's it! Thanks for giving React Router a shot. We hope this tutorial gives yo
[root-route]: ../api/framework-conventions/root.tsx
[error-boundaries]: ../how-to/error-boundary
[links]: ../start/framework/route-module#links
-[outlet-component]: https://api.reactrouter.com/v7/functions/react-router.Outlet
+[outlet-component]: https://api.reactrouter.com/v8/functions/react-router.Outlet
[file-route-conventions]: ../how-to/file-route-conventions
[contacts-1]: http://localhost:5173/contacts/1
-[link-component]: https://api.reactrouter.com/v7/functions/react-router.Link
+[link-component]: https://api.reactrouter.com/v8/variables/react-router.Link.html
[client-loader]: ../start/framework/route-module#clientloader
[spa]: ../how-to/spa
[type-safety]: ../explanation/type-safety
@@ -1959,17 +1959,17 @@ That's it! Thanks for giving React Router a shot. We hope this tutorial gives yo
[url-search-params]: https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams
[loader]: ../start/framework/route-module#loader
[action]: ../start/framework/route-module#action
-[form-component]: https://api.reactrouter.com/v7/functions/react-router.Form
+[form-component]: https://api.reactrouter.com/v8/variables/react-router.Form.html
[fetch]: https://developer.mozilla.org/en-US/docs/Web/API/fetch
[form-data]: https://developer.mozilla.org/en-US/docs/Web/API/FormData
[object-from-entries]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/fromEntries
[request-form-data]: https://developer.mozilla.org/en-US/docs/Web/API/Request/formData
[request]: https://developer.mozilla.org/en-US/docs/Web/API/Request
-[redirect]: https://api.reactrouter.com/v7/functions/react-router.redirect
+[redirect]: https://api.reactrouter.com/v8/variables/react-router.redirect.html
[response]: https://developer.mozilla.org/en-US/docs/Web/API/Response
-[nav-link]: https://api.reactrouter.com/v7/functions/react-router.NavLink
-[use-navigation]: https://api.reactrouter.com/v7/functions/react-router.useNavigation
-[use-navigate]: https://api.reactrouter.com/v7/functions/react-router.useNavigate
-[use-submit]: https://api.reactrouter.com/v7/functions/react-router.useSubmit
-[use-fetcher]: https://api.reactrouter.com/v7/functions/react-router.useFetcher
-[react-router-apis]: https://api.reactrouter.com/v7/modules/react_router
+[nav-link]: https://api.reactrouter.com/v8/variables/react-router.NavLink.html
+[use-navigation]: https://api.reactrouter.com/v8/functions/react-router.useNavigation
+[use-navigate]: https://api.reactrouter.com/v8/functions/react-router.useNavigate
+[use-submit]: https://api.reactrouter.com/v8/functions/react-router.useSubmit
+[use-fetcher]: https://api.reactrouter.com/v8/functions/react-router.useFetcher
+[react-router-apis]: https://api.reactrouter.com/v8/modules/react-router.html
diff --git a/docs/tutorials/quickstart.md b/docs/tutorials/quickstart.md
index 6f52add340..5e05a18882 100644
--- a/docs/tutorials/quickstart.md
+++ b/docs/tutorials/quickstart.md
@@ -294,7 +294,7 @@ What's next?
[routing]: ../start/framework/routing
[http-localhost-3000]: http://localhost:3000
[vite]: https://vitejs.dev
-[react-router-config]: https://api.reactrouter.com/v7/types/_react-router_dev.config.Config.html
+[react-router-config]: https://api.reactrouter.com/v8/types/_react-router_dev.config.Config.html
[vite-middleware]: https://vitejs.dev/guide/ssr#setting-up-the-dev-server
[cross-env]: https://www.npmjs.com/package/cross-env
[address-book-tutorial]: ./address-book
diff --git a/packages/react-router/lib/dom/dom.ts b/packages/react-router/lib/dom/dom.ts
index 5a84f3ca7a..73e53a4c39 100644
--- a/packages/react-router/lib/dom/dom.ts
+++ b/packages/react-router/lib/dom/dom.ts
@@ -51,30 +51,30 @@ export type URLSearchParamsInit =
| URLSearchParams;
/**
- Creates a URLSearchParams object using the given initializer.
-
- This is identical to `new URLSearchParams(init)` except it also
- supports arrays as values in the object form of the initializer
- instead of just strings. This is convenient when you need multiple
- values for a given key, but don't want to use an array initializer.
-
- For example, instead of:
-
- ```tsx
- let searchParams = new URLSearchParams([
- ['sort', 'name'],
- ['sort', 'price']
- ]);
- ```
- you can do:
-
- ```
- let searchParams = createSearchParams({
- sort: ['name', 'price']
- });
- ```
-
- @category Utils
+ * Creates a URLSearchParams object using the given initializer.
+ *
+ * This is identical to `new URLSearchParams(init)` except it also supports
+ * arrays as values in the object form of the initializer instead of just
+ * strings. This is convenient when you need multiple values for a given key,
+ * but don't want to use an array initializer.
+ *
+ * @example
+ * // Instead of:
+ * let searchParams = new URLSearchParams([
+ * ["sort", "name"],
+ * ["sort", "price"],
+ * ]);
+ *
+ * // You can do:
+ * let searchParams = createSearchParams({
+ * sort: ["name", "price"],
+ * });
+ *
+ * @public
+ * @category Utils
+ * @param init The value used to initialize the URL search parameters.
+ * @returns A URLSearchParams object containing the initialized search
+ * parameters.
*/
export function createSearchParams(
init: URLSearchParamsInit = "",
diff --git a/packages/react-router/lib/dom/ssr/routes-test-stub.tsx b/packages/react-router/lib/dom/ssr/routes-test-stub.tsx
index 9b0f707838..ca26504d17 100644
--- a/packages/react-router/lib/dom/ssr/routes-test-stub.tsx
+++ b/packages/react-router/lib/dom/ssr/routes-test-stub.tsx
@@ -109,7 +109,20 @@ export interface RoutesTestStubProps {
}
/**
+ * Creates a React component that renders the provided routes in a test-friendly
+ * React Router context.
+ *
+ * Use this to unit test components that rely on router context, such as
+ * `loaderData`, `actionData`, and route matches.
+ *
+ * @public
* @category Utils
+ * @mode framework
+ * @mode data
+ * @param routes The route objects to render in the test router.
+ * @param _context An optional {@link RouterContextProvider} for supplying
+ * application context values to route middleware, loaders, and actions.
+ * @returns A React component that renders the test router.
*/
export function createRoutesStub(
routes: StubRouteObject[],
diff --git a/packages/react-router/lib/router/history.ts b/packages/react-router/lib/router/history.ts
index 5c6a72b438..559ea24382 100644
--- a/packages/react-router/lib/router/history.ts
+++ b/packages/react-router/lib/router/history.ts
@@ -596,7 +596,10 @@ export function createLocation(
/**
* Creates a string URL path from the given pathname, search, and hash components.
*
+ * @public
* @category Utils
+ * @param path The pathname, search, and hash components to combine.
+ * @returns The combined URL path.
*/
export function createPath({
pathname = "/",
@@ -613,7 +616,10 @@ export function createPath({
/**
* Parses a string URL path into its separate pathname, search, and hash components.
*
+ * @public
* @category Utils
+ * @param path The URL path to parse.
+ * @returns The parsed pathname, search, and hash components.
*/
export function parsePath(path: string): Partial {
let parsedPath: Partial = {};
diff --git a/packages/react-router/lib/server-runtime/cookies.ts b/packages/react-router/lib/server-runtime/cookies.ts
index dad5833177..3a3fa29346 100644
--- a/packages/react-router/lib/server-runtime/cookies.ts
+++ b/packages/react-router/lib/server-runtime/cookies.ts
@@ -69,6 +69,14 @@ export interface Cookie {
/**
* Creates a logical container for managing a browser cookie from the server.
+ *
+ * @public
+ * @category Utils
+ * @mode framework
+ * @mode data
+ * @param name The name of the cookie.
+ * @param cookieOptions Options for parsing and serializing the cookie.
+ * @returns A {@link Cookie} object for parsing and serializing the cookie.
*/
export const createCookie = (
name: string,
@@ -123,12 +131,30 @@ export const createCookie = (
};
};
+/**
+ * A function that determines whether a value is a React Router {@link Cookie}
+ * object.
+ *
+ * @public
+ * @category Utils
+ * @mode framework
+ * @mode data
+ * @param object The value to check.
+ * @returns `true` if the value is a React Router {@link Cookie} object;
+ * otherwise, `false`.
+ */
export type IsCookieFunction = (object: any) => object is Cookie;
/**
- * Returns true if an object is a Remix cookie container.
+ * Returns `true` if a value is a React Router {@link Cookie} object.
*
- * @see https://remix.run/utils/cookies#iscookie
+ * @public
+ * @category Utils
+ * @mode framework
+ * @mode data
+ * @param object The value to check.
+ * @returns `true` if the value is a React Router {@link Cookie} object;
+ * otherwise, `false`.
*/
export const isCookie: IsCookieFunction = (object): object is Cookie => {
return (
diff --git a/packages/react-router/lib/server-runtime/server.ts b/packages/react-router/lib/server-runtime/server.ts
index 91edf2c315..e1373fe4e3 100644
--- a/packages/react-router/lib/server-runtime/server.ts
+++ b/packages/react-router/lib/server-runtime/server.ts
@@ -325,6 +325,18 @@ function derive(build: ServerBuild, mode?: string) {
};
}
+/**
+ * Creates a request handler for a React Router server build.
+ *
+ * This is a low-level API used by server adapters to translate incoming
+ * requests into React Router responses.
+ *
+ * @category Utils
+ * @param build The server build, or a function that resolves to the server
+ * build, used to handle requests.
+ * @param mode The mode in which the server build is running.
+ * @returns A request handler that returns a response for each incoming request.
+ */
export const createRequestHandler: CreateRequestHandlerFunction = (
build,
mode,
diff --git a/packages/react-router/lib/server-runtime/sessions.ts b/packages/react-router/lib/server-runtime/sessions.ts
index d8b9beaafd..615e23fbff 100644
--- a/packages/react-router/lib/server-runtime/sessions.ts
+++ b/packages/react-router/lib/server-runtime/sessions.ts
@@ -89,6 +89,12 @@ export type CreateSessionFunction = (
*
* Note: This function is typically not invoked directly by application code.
* Instead, use a `SessionStorage` object's `getSession` method.
+ *
+ * @category Utils
+ * @param initialData The initial data for the session.
+ * @param id The identifier for the session. Defaults to an empty string for a
+ * new session.
+ * @returns A new {@link Session} object.
*/
export const createSession: CreateSessionFunction = <
Data = SessionData,
@@ -139,12 +145,30 @@ export const createSession: CreateSessionFunction = <
};
};
+/**
+ * A function that determines whether a value is a React Router {@link Session}
+ * object.
+ *
+ * @public
+ * @category Utils
+ * @mode framework
+ * @mode data
+ * @param object The value to check.
+ * @returns `true` if the value is a React Router {@link Session} object;
+ * otherwise, `false`.
+ */
export type IsSessionFunction = (object: any) => object is Session;
/**
- * Returns true if an object is a React Router session.
+ * Returns `true` if a value is a React Router {@link Session} object.
*
- * @see https://reactrouter.com/api/utils/isSession
+ * @public
+ * @category Utils
+ * @mode framework
+ * @mode data
+ * @param object The value to check.
+ * @returns `true` if the value is a React Router {@link Session} object;
+ * otherwise, `false`.
*/
export const isSession: IsSessionFunction = (object): object is Session => {
return (
@@ -248,6 +272,11 @@ export interface SessionIdStorageStrategy<
*
* Note: This is a low-level API that should only be used if none of the
* existing session storage options meet your requirements.
+ *
+ * @category Utils
+ * @param strategy The strategy used to store session identifiers and data.
+ * @returns A {@link SessionStorage} object that persists session data using the
+ * provided strategy.
*/
export function createSessionStorage({
cookie: cookieArg,
diff --git a/packages/react-router/lib/server-runtime/sessions/cookieStorage.ts b/packages/react-router/lib/server-runtime/sessions/cookieStorage.ts
index 4059e495d0..776a157a8b 100644
--- a/packages/react-router/lib/server-runtime/sessions/cookieStorage.ts
+++ b/packages/react-router/lib/server-runtime/sessions/cookieStorage.ts
@@ -22,6 +22,14 @@ interface CookieSessionStorageOptions {
* needed, and can help to simplify some load-balanced scenarios. However, it
* also has the limitation that serialized session data may not exceed the
* browser's maximum cookie size. Trade-offs!
+ *
+ * @public
+ * @category Utils
+ * @mode framework
+ * @mode data
+ * @param options Options for creating the cookie-backed session storage.
+ * @returns A {@link SessionStorage} object that stores all session data in its
+ * cookie.
*/
export function createCookieSessionStorage<
Data = SessionData,
diff --git a/packages/react-router/lib/server-runtime/sessions/memoryStorage.ts b/packages/react-router/lib/server-runtime/sessions/memoryStorage.ts
index d39ea62c7a..f748466766 100644
--- a/packages/react-router/lib/server-runtime/sessions/memoryStorage.ts
+++ b/packages/react-router/lib/server-runtime/sessions/memoryStorage.ts
@@ -19,6 +19,13 @@ interface MemorySessionStorageOptions {
*
* Intended for local development and testing. It does not scale beyond a single
* process, and all session data is lost when the server process stops/restarts.
+ *
+ * @public
+ * @category Utils
+ * @mode framework
+ * @mode data
+ * @param options Options for creating the in-memory session storage.
+ * @returns A {@link SessionStorage} object that stores session data in memory.
*/
export function createMemorySessionStorage<
Data = SessionData,
diff --git a/scripts/docs.ts b/scripts/docs.ts
index f5db20ec5b..f07f011997 100644
--- a/scripts/docs.ts
+++ b/scripts/docs.ts
@@ -570,6 +570,11 @@ function getApiName(comment: ParsedComment): string {
return matches[1].trim();
}
+ matches = comment.code.match(/^export type ([^<=]+)/);
+ if (matches) {
+ return matches[1].trim();
+ }
+
throw new Error(`Could not determine API name:\n${comment.code}\n`);
}
@@ -713,7 +718,7 @@ async function getSignature(code: string) {
let formatted = await prettier.format(newCode, { parser: "typescript" });
- return formatted.replace("{}", "").trim();
+ return formatted.replace(/\s*\{\}\s*$/, "").trim();
}
// TODO: Handle variable statements for forwardRef components
@@ -731,6 +736,22 @@ async function getSignature(code: string) {
return;
}
+ if (ts.isTypeAliasDeclaration(ast.statements[0])) {
+ let typeAliasDeclaration = ast.statements[0];
+ let modifiedTypeAlias = {
+ ...typeAliasDeclaration,
+ modifiers: typeAliasDeclaration.modifiers?.filter(
+ (m) => m.kind !== ts.SyntaxKind.ExportKeyword,
+ ),
+ } as ts.TypeAliasDeclaration;
+
+ let newCode = ts
+ .createPrinter({ newLine: ts.NewLineKind.LineFeed })
+ .printNode(ts.EmitHint.Unspecified, modifiedTypeAlias, ast);
+
+ return (await prettier.format(newCode, { parser: "typescript" })).trim();
+ }
+
throw new Error("Unable to parse signature from code: " + code);
}