diff --git a/.changeset/splat-form-action.md b/.changeset/splat-form-action.md deleted file mode 100644 index 4c3c7fe3aa..0000000000 --- a/.changeset/splat-form-action.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"react-router-dom": patch ---- - -Ensure `
` default action contains splat portion of pathname when no `action` is specified diff --git a/packages/react-router-dom/__tests__/data-browser-router-test.tsx b/packages/react-router-dom/__tests__/data-browser-router-test.tsx index 4d335c7c2a..fdc3b09c1f 100644 --- a/packages/react-router-dom/__tests__/data-browser-router-test.tsx +++ b/packages/react-router-dom/__tests__/data-browser-router-test.tsx @@ -2894,7 +2894,7 @@ function testDomRouter( let { container } = render(); expect(container.querySelector("form")?.getAttribute("action")).toBe( - "/foo/bar?a=1" + "/foo?a=1" ); }); @@ -2937,44 +2937,6 @@ function testDomRouter( "/foo" ); }); - - it("includes splat portion of path when no action is specified (inline splat)", async () => { - let router = createTestRouter( - createRoutesFromElements( - - - } /> - - - ), - { - window: getWindow("/foo/bar/baz"), - } - ); - let { container } = render(); - - expect(container.querySelector("form")?.getAttribute("action")).toBe( - "/foo/bar/baz" - ); - }); - - it("includes splat portion of path when no action is specified (nested splat)", async () => { - let router = createTestRouter( - createRoutesFromElements( - - } /> - - ), - { - window: getWindow("/foo/bar/baz"), - } - ); - let { container } = render(); - - expect(container.querySelector("form")?.getAttribute("action")).toBe( - "/foo/bar/baz" - ); - }); }); it("allows user to specify search params and hash", async () => { diff --git a/packages/react-router-dom/index.tsx b/packages/react-router-dom/index.tsx index f115357c4f..8c62c56893 100644 --- a/packages/react-router-dom/index.tsx +++ b/packages/react-router-dom/index.tsx @@ -1457,20 +1457,18 @@ export function useFormAction( let { basename } = React.useContext(NavigationContext); let routeContext = React.useContext(RouteContext); invariant(routeContext, "useFormAction must be used inside a RouteContext"); - let location = useLocation(); let [match] = routeContext.matches.slice(-1); // Shallow clone path so we can modify it below, otherwise we modify the // object referenced by useMemo inside useResolvedPath - let path = { - ...useResolvedPath(action != null ? action : location.pathname, { - relative, - }), - }; + let path = { ...useResolvedPath(action ? action : ".", { relative }) }; - // If no action was specified, browsers will persist current search params - // when determining the path, so match that behavior + // Previously we set the default action to ".". The problem with this is that + // `useResolvedPath(".")` excludes search params of the resolved URL. This is + // the intended behavior of when "." is specifically provided as + // the form action, but inconsistent w/ browsers when the action is omitted. // https://github.com/remix-run/remix/issues/927 + let location = useLocation(); if (action == null) { // Safe to write to this directly here since if action was undefined, we // would have called useResolvedPath(".") which will never include a search