diff --git a/.changeset/purple-islands-cough.md b/.changeset/purple-islands-cough.md new file mode 100644 index 0000000000..ab9b2a3bb2 --- /dev/null +++ b/.changeset/purple-islands-cough.md @@ -0,0 +1,5 @@ +--- +"react-router": patch +--- + +Fix `generatePath` when passed a numeric `0` value parameter diff --git a/packages/react-router/__tests__/generatePath-test.tsx b/packages/react-router/__tests__/generatePath-test.tsx index 16f2f8a5b3..fe5e860056 100644 --- a/packages/react-router/__tests__/generatePath-test.tsx +++ b/packages/react-router/__tests__/generatePath-test.tsx @@ -44,6 +44,14 @@ describe("generatePath", () => { }) ).toBe("/courses/foo*"); }); + it("handles a 0 parameter", () => { + // @ts-expect-error + // incorrect usage but worked in 6.3.0 so keep it to avoid the regression + expect(generatePath("/courses/:id", { id: 0 })).toBe("/courses/0"); + // @ts-expect-error + // incorrect usage but worked in 6.3.0 so keep it to avoid the regression + expect(generatePath("/courses/*", { "*": 0 })).toBe("/courses/0"); + }); }); describe("with extraneous params", () => { diff --git a/packages/router/utils.ts b/packages/router/utils.ts index 5a288734f7..6c7796ed3f 100644 --- a/packages/router/utils.ts +++ b/packages/router/utils.ts @@ -762,6 +762,9 @@ export function generatePath( // ensure `/` is added at the beginning if the path is absolute const prefix = path.startsWith("/") ? "/" : ""; + const stringify = (p: any) => + p == null ? "" : typeof p === "string" ? p : String(p); + const segments = path .split(/\/+/) .map((segment, index, array) => { @@ -770,26 +773,16 @@ export function generatePath( // only apply the splat if it's the last segment if (isLastSegment && segment === "*") { const star = "*" as PathParam; - const starParam = params[star]; - // Apply the splat - return starParam; + return stringify(params[star]); } const keyMatch = segment.match(/^:(\w+)(\??)$/); if (keyMatch) { const [, key, optional] = keyMatch; let param = params[key as PathParam]; - - if (optional === "?") { - return param == null ? "" : param; - } - - if (param == null) { - invariant(false, `Missing ":${key}" param`); - } - - return param; + invariant(optional === "?" || param != null, `Missing ":${key}" param`); + return stringify(param); } // Remove any optional markers from optional static segments