diff --git a/packages/react-dom-bindings/src/events/plugins/FormActionEventPlugin.js b/packages/react-dom-bindings/src/events/plugins/FormActionEventPlugin.js index 496b55e15e79b..420d1d1188209 100644 --- a/packages/react-dom-bindings/src/events/plugins/FormActionEventPlugin.js +++ b/packages/react-dom-bindings/src/events/plugins/FormActionEventPlugin.js @@ -45,30 +45,6 @@ function coerceFormActionProp( } } -function createFormDataWithSubmitter( - form: HTMLFormElement, - submitter: HTMLInputElement | HTMLButtonElement, -) { - // The submitter's value should be included in the FormData. - // It should be in the document order in the form. - // Since the FormData constructor invokes the formdata event it also - // needs to be available before that happens so after construction it's too - // late. We use a temporary fake node for the duration of this event. - // TODO: FormData takes a second argument that it's the submitter but this - // is fairly new so not all browsers support it yet. Switch to that technique - // when available. - const temp = submitter.ownerDocument.createElement('input'); - temp.name = submitter.name; - temp.value = submitter.value; - if (form.id) { - temp.setAttribute('form', form.id); - } - (submitter.parentNode: any).insertBefore(temp, submitter); - const formData = new FormData(form); - (temp.parentNode: any).removeChild(temp); - return formData; -} - /** * This plugin invokes action functions on forms, inputs and buttons if * the form doesn't prevent default. @@ -129,9 +105,7 @@ function extractEvents( if (didCurrentEventScheduleTransition()) { // We're going to set the pending form status, but because the submission // was prevented, we should not fire the action function. - const formData = submitter - ? createFormDataWithSubmitter(form, submitter) - : new FormData(form); + const formData = new FormData(form, submitter); const pendingState: FormStatus = { pending: true, data: formData, @@ -160,9 +134,7 @@ function extractEvents( event.preventDefault(); // Dispatch the action and set a pending form status. - const formData = submitter - ? createFormDataWithSubmitter(form, submitter) - : new FormData(form); + const formData = new FormData(form, submitter); const pendingState: FormStatus = { pending: true, data: formData, diff --git a/packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetInlineCodeStrings.js b/packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetInlineCodeStrings.js index 6e47c3b0658e3..38f43b1f0a0d3 100644 --- a/packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetInlineCodeStrings.js +++ b/packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetInlineCodeStrings.js @@ -10,4 +10,4 @@ export const completeBoundaryWithStyles = export const completeSegment = '$RS=function(a,b){a=document.getElementById(a);b=document.getElementById(b);for(a.parentNode.removeChild(a);a.firstChild;)b.parentNode.insertBefore(a.firstChild,b);b.parentNode.removeChild(b)};'; export const formReplaying = - 'addEventListener("submit",function(a){if(!a.defaultPrevented){var c=a.target,d=a.submitter,e=c.action,b=d;if(d){var f=d.getAttribute("formAction");null!=f&&(e=f,b=null)}"javascript:throw new Error(\'React form unexpectedly submitted.\')"===e&&(a.preventDefault(),b?(a=document.createElement("input"),a.name=b.name,a.value=b.value,b.parentNode.insertBefore(a,b),b=new FormData(c),a.parentNode.removeChild(a)):b=new FormData(c),a=c.ownerDocument||c,(a.$$reactFormReplay=a.$$reactFormReplay||[]).push(c,d,b))}});'; + 'addEventListener("submit",function(a){if(!a.defaultPrevented){var b=a.target,d=a.submitter,c=b.action,e=d;if(d){var f=d.getAttribute("formAction");null!=f&&(c=f,e=null)}"javascript:throw new Error(\'React form unexpectedly submitted.\')"===c&&(a.preventDefault(),a=new FormData(b,e),c=b.ownerDocument||b,(c.$$reactFormReplay=c.$$reactFormReplay||[]).push(b,d,a))}});'; diff --git a/packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetShared.js b/packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetShared.js index f9139094aa9b5..fcac0c58c9687 100644 --- a/packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetShared.js +++ b/packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetShared.js @@ -172,25 +172,7 @@ export function listenToFormSubmissionsForReplaying() { event.preventDefault(); // Take a snapshot of the FormData at the time of the event. - let formData; - if (formDataSubmitter) { - // The submitter's value should be included in the FormData. - // It should be in the document order in the form. - // Since the FormData constructor invokes the formdata event it also - // needs to be available before that happens so after construction it's too - // late. We use a temporary fake node for the duration of this event. - // TODO: FormData takes a second argument that it's the submitter but this - // is fairly new so not all browsers support it yet. Switch to that technique - // when available. - const temp = document.createElement('input'); - temp.name = formDataSubmitter.name; - temp.value = formDataSubmitter.value; - formDataSubmitter.parentNode.insertBefore(temp, formDataSubmitter); - formData = new FormData(form); - temp.parentNode.removeChild(temp); - } else { - formData = new FormData(form); - } + const formData = new FormData(form, formDataSubmitter); // Queue for replaying later. This field could potentially be shared with multiple // Reacts on the same page since each one will preventDefault for the next one. diff --git a/packages/react-dom/src/__tests__/ReactDOMForm-test.js b/packages/react-dom/src/__tests__/ReactDOMForm-test.js index 168d44722d473..6290ad7ce78c0 100644 --- a/packages/react-dom/src/__tests__/ReactDOMForm-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMForm-test.js @@ -14,8 +14,8 @@ global.IS_REACT_ACT_ENVIRONMENT = true; // Our current version of JSDOM doesn't implement the event dispatching // so we polyfill it. const NativeFormData = global.FormData; -const FormDataPolyfill = function FormData(form) { - const formData = new NativeFormData(form); +const FormDataPolyfill = function FormData(form, submitter) { + const formData = new NativeFormData(form, submitter); const formDataEvent = new Event('formdata', { bubbles: true, cancelable: false, @@ -491,11 +491,16 @@ describe('ReactDOMForm', () => { const inputRef = React.createRef(); const buttonRef = React.createRef(); const outsideButtonRef = React.createRef(); + const imageButtonRef = React.createRef(); let button; + let buttonX; + let buttonY; let title; function action(formData) { button = formData.get('button'); + buttonX = formData.get('button.x'); + buttonY = formData.get('button.y'); title = formData.get('title'); } @@ -510,6 +515,12 @@ describe('ReactDOMForm', () => { +