diff --git a/.changeset/v2-remove-normalize-form-method.md b/.changeset/v2-remove-normalize-form-method.md
new file mode 100644
index 00000000000..f15c335dadd
--- /dev/null
+++ b/.changeset/v2-remove-normalize-form-method.md
@@ -0,0 +1,9 @@
+---
+"@remix-run/dev": major
+"@remix-run/eslint-config": major
+"@remix-run/react": major
+"@remix-run/server-runtime": major
+"@remix-run/testing": major
+---
+
+Remove `v2_normalizeFormMethod` future flag - all `formMethod` values will be normalized in v2
diff --git a/docs/hooks/use-navigation.md b/docs/hooks/use-navigation.md
index 22f915491b0..07dec23017b 100644
--- a/docs/hooks/use-navigation.md
+++ b/docs/hooks/use-navigation.md
@@ -20,8 +20,6 @@ function SomeComponent() {
}
```
-The `useNavigation().formMethod` field is lowercase without the `future.v2_normalizeFormMethod` [Future Flag][api-development-strategy]. This is being normalized to uppercase to align with the `fetch()` behavior in v2, so please upgrade your Remix v1 applications to adopt the uppercase HTTP methods.
-
For more information and usage, please refer to the [React Router `useNavigation` docs][rr-usenavigation].
[rr-usenavigation]: https://reactrouter.com/hooks/use-navigation
diff --git a/docs/pages/api-development-strategy.md b/docs/pages/api-development-strategy.md
index 49820c1d2fa..4ba18fe57c5 100644
--- a/docs/pages/api-development-strategy.md
+++ b/docs/pages/api-development-strategy.md
@@ -50,14 +50,13 @@ The lifecycle is thus either:
## Current Future Flags
-| Flag | Description |
-| ------------------------ | --------------------------------------------------------------------- |
-| `v2_dev` | Enable the new development server (including HMR/HDR support) |
-| `v2_errorBoundary` | Combine `ErrorBoundary`/`CatchBoundary` into a single `ErrorBoundary` |
-| `v2_headers` | Leverage ancestor `headers` if children do not export `headers` |
-| `v2_meta` | Enable the new API for your `meta` functions |
-| `v2_normalizeFormMethod` | Normalize `useNavigation().formMethod` to be an uppercase HTTP Method |
-| `v2_routeConvention` | Enable the flat routes style of file-based routing |
+| Flag | Description |
+| -------------------- | --------------------------------------------------------------------- |
+| `v2_dev` | Enable the new development server (including HMR/HDR support) |
+| `v2_errorBoundary` | Combine `ErrorBoundary`/`CatchBoundary` into a single `ErrorBoundary` |
+| `v2_headers` | Leverage ancestor `headers` if children do not export `headers` |
+| `v2_meta` | Enable the new API for your `meta` functions |
+| `v2_routeConvention` | Enable the flat routes style of file-based routing |
[future-flags-blog-post]: https://remix.run/blog/future-flags
[feature-flowchart]: /docs-images/feature-flowchart.png
diff --git a/integration/action-test.ts b/integration/action-test.ts
index 4154ba7696c..51e57026860 100644
--- a/integration/action-test.ts
+++ b/integration/action-test.ts
@@ -21,7 +21,6 @@ test.describe("actions", () => {
future: {
v2_routeConvention: true,
v2_errorBoundary: true,
- v2_normalizeFormMethod: true,
},
},
files: {
diff --git a/integration/defer-test.ts b/integration/defer-test.ts
index aa49e5da735..9ffd25ab828 100644
--- a/integration/defer-test.ts
+++ b/integration/defer-test.ts
@@ -46,7 +46,6 @@ test.describe("non-aborted", () => {
future: {
v2_routeConvention: true,
v2_errorBoundary: true,
- v2_normalizeFormMethod: true,
},
},
files: {
diff --git a/integration/hmr-log-test.ts b/integration/hmr-log-test.ts
index 6e3d2ffa466..589c2b54ad1 100644
--- a/integration/hmr-log-test.ts
+++ b/integration/hmr-log-test.ts
@@ -20,7 +20,6 @@ let fixture = (options: { appPort: number; devPort: number }): FixtureInit => ({
},
v2_routeConvention: true,
v2_errorBoundary: true,
- v2_normalizeFormMethod: true,
v2_meta: true,
v2_headers: true,
},
diff --git a/integration/hmr-test.ts b/integration/hmr-test.ts
index f217123e375..b58e7cc037a 100644
--- a/integration/hmr-test.ts
+++ b/integration/hmr-test.ts
@@ -20,7 +20,6 @@ let fixture = (options: { appPort: number; devPort: number }): FixtureInit => ({
},
v2_routeConvention: true,
v2_errorBoundary: true,
- v2_normalizeFormMethod: true,
v2_meta: true,
v2_headers: true,
},
diff --git a/integration/navigation-state-test.ts b/integration/navigation-state-test.ts
index 9bf19ff603b..319e9b58fea 100644
--- a/integration/navigation-state-test.ts
+++ b/integration/navigation-state-test.ts
@@ -31,11 +31,6 @@ test.describe("navigation states", () => {
test.beforeAll(async () => {
fixture = await createFixture({
- config: {
- future: {
- v2_normalizeFormMethod: true,
- },
- },
files: {
"app/root.jsx": js`
import { useMemo, useRef } from "react";
diff --git a/packages/remix-dev/__tests__/readConfig-test.ts b/packages/remix-dev/__tests__/readConfig-test.ts
index 5eeb555d3b9..4c7e21a6d3f 100644
--- a/packages/remix-dev/__tests__/readConfig-test.ts
+++ b/packages/remix-dev/__tests__/readConfig-test.ts
@@ -30,7 +30,6 @@ describe("readConfig", () => {
v2_errorBoundary: expect.any(Boolean),
v2_headers: expect.any(Boolean),
v2_meta: expect.any(Boolean),
- v2_normalizeFormMethod: expect.any(Boolean),
v2_routeConvention: expect.any(Boolean),
},
},
@@ -52,7 +51,6 @@ describe("readConfig", () => {
"v2_errorBoundary": Any,
"v2_headers": Any,
"v2_meta": Any,
- "v2_normalizeFormMethod": Any,
"v2_routeConvention": Any,
},
"mdx": undefined,
diff --git a/packages/remix-dev/config.ts b/packages/remix-dev/config.ts
index 8c58149843e..af326fe24ba 100644
--- a/packages/remix-dev/config.ts
+++ b/packages/remix-dev/config.ts
@@ -61,7 +61,6 @@ interface FutureConfig {
v2_errorBoundary: boolean;
v2_headers: boolean;
v2_meta: boolean;
- v2_normalizeFormMethod: boolean;
v2_routeConvention: boolean;
}
@@ -456,10 +455,6 @@ export async function readConfig(
errorBoundaryWarning();
}
- if (!appConfig.future?.v2_normalizeFormMethod) {
- formMethodWarning();
- }
-
if (!appConfig.future?.v2_meta) {
metaWarning();
}
@@ -882,7 +877,6 @@ export async function readConfig(
v2_errorBoundary: appConfig.future?.v2_errorBoundary === true,
v2_headers: appConfig.future?.v2_headers === true,
v2_meta: appConfig.future?.v2_meta === true,
- v2_normalizeFormMethod: appConfig.future?.v2_normalizeFormMethod === true,
v2_routeConvention: appConfig.future?.v2_routeConvention === true,
};
@@ -1104,12 +1098,6 @@ let errorBoundaryWarning = futureFlagWarning({
link: "https://remix.run/docs/en/v1.15.0/pages/v2#catchboundary-and-errorboundary",
});
-let formMethodWarning = futureFlagWarning({
- message: "The `formMethod` API is changing in v2",
- flag: "v2_normalizeFormMethod",
- link: "https://remix.run/docs/en/v1.15.0/pages/v2#formMethod",
-});
-
let metaWarning = futureFlagWarning({
message: "The route `meta` API is changing in v2",
flag: "v2_meta",
diff --git a/packages/remix-react/browser.tsx b/packages/remix-react/browser.tsx
index a18bb8850d5..c877d25d180 100644
--- a/packages/remix-react/browser.tsx
+++ b/packages/remix-react/browser.tsx
@@ -193,13 +193,7 @@ export function RemixBrowser(_props: RemixBrowserProps): ReactElement {
router = createBrowserRouter(routes, {
hydrationData,
future: {
- // Pass through the Remix future flag to avoid a v1 breaking change in
- // useNavigation() - users can control the casing via the flag in v1.
- // useFetcher still always uppercases in the back-compat layer in v1.
- // In v2 we can just always pass true here and remove the back-compat
- // layer
- v7_normalizeFormMethod:
- window.__remixContext.future.v2_normalizeFormMethod,
+ v7_normalizeFormMethod: true,
},
});
diff --git a/packages/remix-react/entry.ts b/packages/remix-react/entry.ts
index 2462c016fe7..d038c37d7f9 100644
--- a/packages/remix-react/entry.ts
+++ b/packages/remix-react/entry.ts
@@ -41,7 +41,6 @@ export interface FutureConfig {
v2_errorBoundary: boolean;
v2_headers: boolean;
v2_meta: boolean;
- v2_normalizeFormMethod: boolean;
v2_routeConvention: boolean;
}
diff --git a/packages/remix-server-runtime/entry.ts b/packages/remix-server-runtime/entry.ts
index b20be17e389..4d23a69bbbc 100644
--- a/packages/remix-server-runtime/entry.ts
+++ b/packages/remix-server-runtime/entry.ts
@@ -29,7 +29,6 @@ export interface FutureConfig {
v2_errorBoundary: boolean;
v2_headers: boolean;
v2_meta: boolean;
- v2_normalizeFormMethod: boolean;
v2_routeConvention: boolean;
}
diff --git a/packages/remix-testing/create-remix-stub.tsx b/packages/remix-testing/create-remix-stub.tsx
index 6d4fae6bb25..f4c68124f98 100644
--- a/packages/remix-testing/create-remix-stub.tsx
+++ b/packages/remix-testing/create-remix-stub.tsx
@@ -130,7 +130,6 @@ export function createRemixStub(
v2_errorBoundary: false,
v2_headers: false,
v2_meta: false,
- v2_normalizeFormMethod: false,
v2_routeConvention: false,
...remixConfigFuture,
},
diff --git a/templates/arc/remix.config.js b/templates/arc/remix.config.js
index c0345763aae..6ab9f8eee67 100644
--- a/templates/arc/remix.config.js
+++ b/templates/arc/remix.config.js
@@ -12,7 +12,6 @@ export default {
v2_errorBoundary: true,
v2_headers: true,
v2_meta: true,
- v2_normalizeFormMethod: true,
v2_routeConvention: true,
},
};
diff --git a/templates/cloudflare-pages/remix.config.js b/templates/cloudflare-pages/remix.config.js
index d31efea86fe..8fb267610fd 100644
--- a/templates/cloudflare-pages/remix.config.js
+++ b/templates/cloudflare-pages/remix.config.js
@@ -18,7 +18,6 @@ export default {
v2_errorBoundary: true,
v2_headers: true,
v2_meta: true,
- v2_normalizeFormMethod: true,
v2_routeConvention: true,
},
};
diff --git a/templates/cloudflare-workers/remix.config.js b/templates/cloudflare-workers/remix.config.js
index b971b575863..1887bd531e5 100644
--- a/templates/cloudflare-workers/remix.config.js
+++ b/templates/cloudflare-workers/remix.config.js
@@ -20,7 +20,6 @@ export default {
v2_errorBoundary: true,
v2_headers: true,
v2_meta: true,
- v2_normalizeFormMethod: true,
v2_routeConvention: true,
},
};
diff --git a/templates/deno/remix.config.js b/templates/deno/remix.config.js
index d0c78e97eef..8da899e0c26 100644
--- a/templates/deno/remix.config.js
+++ b/templates/deno/remix.config.js
@@ -22,7 +22,6 @@ module.exports = {
v2_errorBoundary: true,
v2_headers: true,
v2_meta: true,
- v2_normalizeFormMethod: true,
v2_routeConvention: true,
},
};
diff --git a/templates/express/remix.config.js b/templates/express/remix.config.js
index 378d0fc051f..77275da4ce2 100644
--- a/templates/express/remix.config.js
+++ b/templates/express/remix.config.js
@@ -11,7 +11,6 @@ export default {
v2_errorBoundary: true,
v2_headers: true,
v2_meta: true,
- v2_normalizeFormMethod: true,
v2_routeConvention: true,
},
};
diff --git a/templates/fly/remix.config.js b/templates/fly/remix.config.js
index 60aa1cad1d6..86b6b7000d8 100644
--- a/templates/fly/remix.config.js
+++ b/templates/fly/remix.config.js
@@ -11,7 +11,6 @@ module.exports = {
v2_errorBoundary: true,
v2_headers: true,
v2_meta: true,
- v2_normalizeFormMethod: true,
v2_routeConvention: true,
},
};
diff --git a/templates/netlify/remix.config.js b/templates/netlify/remix.config.js
index f54a5a8d198..62f8db8c29c 100644
--- a/templates/netlify/remix.config.js
+++ b/templates/netlify/remix.config.js
@@ -15,7 +15,6 @@ module.exports = {
v2_errorBoundary: true,
v2_headers: true,
v2_meta: true,
- v2_normalizeFormMethod: true,
v2_routeConvention: true,
},
};
diff --git a/templates/remix/remix.config.js b/templates/remix/remix.config.js
index 60aa1cad1d6..86b6b7000d8 100644
--- a/templates/remix/remix.config.js
+++ b/templates/remix/remix.config.js
@@ -11,7 +11,6 @@ module.exports = {
v2_errorBoundary: true,
v2_headers: true,
v2_meta: true,
- v2_normalizeFormMethod: true,
v2_routeConvention: true,
},
};
diff --git a/templates/vercel/remix.config.js b/templates/vercel/remix.config.js
index f688ad4857b..b49d80dff4e 100644
--- a/templates/vercel/remix.config.js
+++ b/templates/vercel/remix.config.js
@@ -15,7 +15,6 @@ module.exports = {
v2_errorBoundary: true,
v2_headers: true,
v2_meta: true,
- v2_normalizeFormMethod: true,
v2_routeConvention: true,
},
};