diff --git a/.changeset/memory-submit-fetcher.md b/.changeset/memory-submit-fetcher.md
new file mode 100644
index 0000000000..6d05071541
--- /dev/null
+++ b/.changeset/memory-submit-fetcher.md
@@ -0,0 +1,5 @@
+---
+"react-router": minor
+---
+
+Add `useSubmit`/`useFetcher` support to `createMemoryRouter` apps in `react-router` now that we can support non-DOM submissions
diff --git a/docs/hooks/use-fetcher.md b/docs/hooks/use-fetcher.md
index 9f5533ec52..361ccbfa40 100644
--- a/docs/hooks/use-fetcher.md
+++ b/docs/hooks/use-fetcher.md
@@ -82,6 +82,8 @@ function SomeComponent() {
}
```
+`fetcher.Form` is only available in the DOM-based versions of React Router (`createBrowserRouter`and `createHashRouter`) but not in the memory-based versions (`createMemoryRouter`)
+
## `fetcher.load()`
Loads data from a route loader.
diff --git a/docs/hooks/use-submit.md b/docs/hooks/use-submit.md
index 3157066e32..363a6906b8 100644
--- a/docs/hooks/use-submit.md
+++ b/docs/hooks/use-submit.md
@@ -106,7 +106,9 @@ let text = "Plain ol' text";
submit(obj, { encType: "text/plain" }); // -> request.text()
```
-In future versions of React Router, the default behavior will not serialize raw JSON payloads. If you are submitting raw JSON today it's recommended to specify an explicit `encType`.
+If you're using `createMemoryRouter`, then the `FormData` APIs of `useSubmit` aren't relevant, and all submissions are `payload` based.
+
+In future versions of React Router DOM, the default behavior will not serialize raw JSON payloads. If you are submitting raw JSON today it's recommended to specify an explicit `encType`.
### Opting out of serialization
diff --git a/package.json b/package.json
index 227697dde6..3acc238e8e 100644
--- a/package.json
+++ b/package.json
@@ -108,10 +108,10 @@
"none": "45.8 kB"
},
"packages/react-router/dist/react-router.production.min.js": {
- "none": "12.9 kB"
+ "none": "14.0 kB"
},
"packages/react-router/dist/umd/react-router.production.min.js": {
- "none": "15.3 kB"
+ "none": "16.4 kB"
},
"packages/react-router-dom/dist/react-router-dom.production.min.js": {
"none": "12 kB"
diff --git a/packages/react-router-dom/__tests__/exports-test.tsx b/packages/react-router-dom/__tests__/exports-test.tsx
index 46e24e5297..7ad1341859 100644
--- a/packages/react-router-dom/__tests__/exports-test.tsx
+++ b/packages/react-router-dom/__tests__/exports-test.tsx
@@ -3,16 +3,22 @@ import * as ReactRouterDOM from "react-router-dom";
let nonReExportedKeys = new Set(["UNSAFE_mapRouteProperties"]);
+let exportedButDifferent = new Set(["useFetcher", "useFetchers", "useSubmit"]);
+
describe("react-router-dom", () => {
for (let key in ReactRouter) {
- if (!nonReExportedKeys.has(key)) {
- it(`re-exports ${key} from react-router`, () => {
- expect(ReactRouterDOM[key]).toBe(ReactRouter[key]);
- });
- } else {
+ if (nonReExportedKeys.has(key)) {
it(`does not re-export ${key} from react-router`, () => {
expect(ReactRouterDOM[key]).toBe(undefined);
});
+ } else if (exportedButDifferent.has(key)) {
+ it(`exports ${key} but not from react-router`, () => {
+ expect(ReactRouterDOM[key]).not.toBe(ReactRouter[key]);
+ });
+ } else {
+ it(`re-exports ${key} from react-router`, () => {
+ expect(ReactRouterDOM[key]).toBe(ReactRouter[key]);
+ });
}
}
});
diff --git a/packages/react-router-dom/dom.ts b/packages/react-router-dom/dom.ts
index c11c0093c7..d9dbfdd2ac 100644
--- a/packages/react-router-dom/dom.ts
+++ b/packages/react-router-dom/dom.ts
@@ -128,13 +128,14 @@ export interface SubmitOptions {
method?: HTMLFormMethod;
/**
- * The action URL path used to submit the form. Overrides `