diff --git a/packages/react-dom-bindings/src/events/__tests__/form-action-submitters.test.js b/packages/react-dom-bindings/src/events/__tests__/form-action-submitters.test.js
new file mode 100644
index 0000000000000..e49db1d43715c
--- /dev/null
+++ b/packages/react-dom-bindings/src/events/__tests__/form-action-submitters.test.js
@@ -0,0 +1,77 @@
+// @jest-environment jsdom
+
+import * as React from 'react';
+import * as ReactDOMClient from 'react-dom/client';
+import {act} from 'internal-test-utils';
+
+describe('form submitter with input[name="id"]', () => {
+ let container;
+
+ beforeEach(() => {
+ container = document.createElement('div');
+ document.body.appendChild(container);
+ delete window.__SUBMIT_ACTION__;
+ });
+
+ afterEach(() => {
+ document.body.removeChild(container);
+ container = null;
+ delete window.__SUBMIT_ACTION__;
+ });
+
+ it('includes submitter when input[name="id"] exists (button inside form)', async () => {
+ function App() {
+ async function action(fd) {
+ window.__SUBMIT_ACTION__ = fd.get('action');
+ }
+ return (
+
+ );
+ }
+
+ await act(async () => {
+ const root = ReactDOMClient.createRoot(container);
+ root.render();
+ });
+
+ await act(async () => {
+ container.querySelector('button').click();
+ });
+
+ expect(window.__SUBMIT_ACTION__).toBe('save');
+ });
+
+ it('includes submitter when using external button with form attribute', async () => {
+ function AppExternal() {
+ async function action(fd) {
+ window.__SUBMIT_ACTION__ = fd.get('action');
+ }
+ return (
+ <>
+
+
+ >
+ );
+ }
+
+ await act(async () => {
+ const root = ReactDOMClient.createRoot(container);
+ root.render();
+ });
+
+ await act(async () => {
+ container.querySelector('button').click();
+ });
+
+ expect(window.__SUBMIT_ACTION__).toBe('save');
+ });
+});
diff --git a/packages/react-dom-bindings/src/events/plugins/FormActionEventPlugin.js b/packages/react-dom-bindings/src/events/plugins/FormActionEventPlugin.js
index 496b55e15e79b..37d602eb6207e 100644
--- a/packages/react-dom-bindings/src/events/plugins/FormActionEventPlugin.js
+++ b/packages/react-dom-bindings/src/events/plugins/FormActionEventPlugin.js
@@ -60,9 +60,16 @@ function createFormDataWithSubmitter(
const temp = submitter.ownerDocument.createElement('input');
temp.name = submitter.name;
temp.value = submitter.value;
- if (form.id) {
- temp.setAttribute('form', form.id);
+
+ // Use the form element's *id attribute*. A named control like
+ // can clobber the `form.id` property to point to that control instead of the
+ // element's id attribute.
+ const formId =
+ typeof form.getAttribute === 'function' ? form.getAttribute('id') : null;
+ if (formId) {
+ temp.setAttribute('form', formId);
}
+
(submitter.parentNode: any).insertBefore(temp, submitter);
const formData = new FormData(form);
(temp.parentNode: any).removeChild(temp);