Skip to content

Commit b1117e6

Browse files
committed
Use FormData submitter parameter
1 parent b9b510d commit b1117e6

File tree

5 files changed

+24
-66
lines changed

5 files changed

+24
-66
lines changed

packages/react-dom-bindings/src/events/plugins/FormActionEventPlugin.js

Lines changed: 2 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -45,30 +45,6 @@ function coerceFormActionProp(
4545
}
4646
}
4747

48-
function createFormDataWithSubmitter(
49-
form: HTMLFormElement,
50-
submitter: HTMLInputElement | HTMLButtonElement,
51-
) {
52-
// The submitter's value should be included in the FormData.
53-
// It should be in the document order in the form.
54-
// Since the FormData constructor invokes the formdata event it also
55-
// needs to be available before that happens so after construction it's too
56-
// late. We use a temporary fake node for the duration of this event.
57-
// TODO: FormData takes a second argument that it's the submitter but this
58-
// is fairly new so not all browsers support it yet. Switch to that technique
59-
// when available.
60-
const temp = submitter.ownerDocument.createElement('input');
61-
temp.name = submitter.name;
62-
temp.value = submitter.value;
63-
if (form.id) {
64-
temp.setAttribute('form', form.id);
65-
}
66-
(submitter.parentNode: any).insertBefore(temp, submitter);
67-
const formData = new FormData(form);
68-
(temp.parentNode: any).removeChild(temp);
69-
return formData;
70-
}
71-
7248
/**
7349
* This plugin invokes action functions on forms, inputs and buttons if
7450
* the form doesn't prevent default.
@@ -129,9 +105,7 @@ function extractEvents(
129105
if (didCurrentEventScheduleTransition()) {
130106
// We're going to set the pending form status, but because the submission
131107
// was prevented, we should not fire the action function.
132-
const formData = submitter
133-
? createFormDataWithSubmitter(form, submitter)
134-
: new FormData(form);
108+
const formData = new FormData(form, submitter);
135109
const pendingState: FormStatus = {
136110
pending: true,
137111
data: formData,
@@ -160,9 +134,7 @@ function extractEvents(
160134
event.preventDefault();
161135

162136
// Dispatch the action and set a pending form status.
163-
const formData = submitter
164-
? createFormDataWithSubmitter(form, submitter)
165-
: new FormData(form);
137+
const formData = new FormData(form, submitter);
166138
const pendingState: FormStatus = {
167139
pending: true,
168140
data: formData,

packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetInlineCodeStrings.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetShared.js

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -172,25 +172,7 @@ export function listenToFormSubmissionsForReplaying() {
172172
event.preventDefault();
173173

174174
// Take a snapshot of the FormData at the time of the event.
175-
let formData;
176-
if (formDataSubmitter) {
177-
// The submitter's value should be included in the FormData.
178-
// It should be in the document order in the form.
179-
// Since the FormData constructor invokes the formdata event it also
180-
// needs to be available before that happens so after construction it's too
181-
// late. We use a temporary fake node for the duration of this event.
182-
// TODO: FormData takes a second argument that it's the submitter but this
183-
// is fairly new so not all browsers support it yet. Switch to that technique
184-
// when available.
185-
const temp = document.createElement('input');
186-
temp.name = formDataSubmitter.name;
187-
temp.value = formDataSubmitter.value;
188-
formDataSubmitter.parentNode.insertBefore(temp, formDataSubmitter);
189-
formData = new FormData(form);
190-
temp.parentNode.removeChild(temp);
191-
} else {
192-
formData = new FormData(form);
193-
}
175+
const formData = new FormData(form, formDataSubmitter);
194176

195177
// Queue for replaying later. This field could potentially be shared with multiple
196178
// Reacts on the same page since each one will preventDefault for the next one.

packages/react-dom/src/__tests__/ReactDOMForm-test.js

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ global.IS_REACT_ACT_ENVIRONMENT = true;
1414
// Our current version of JSDOM doesn't implement the event dispatching
1515
// so we polyfill it.
1616
const NativeFormData = global.FormData;
17-
const FormDataPolyfill = function FormData(form) {
18-
const formData = new NativeFormData(form);
17+
const FormDataPolyfill = function FormData(form, submitter) {
18+
const formData = new NativeFormData(form, submitter);
1919
const formDataEvent = new Event('formdata', {
2020
bubbles: true,
2121
cancelable: false,
@@ -491,11 +491,16 @@ describe('ReactDOMForm', () => {
491491
const inputRef = React.createRef();
492492
const buttonRef = React.createRef();
493493
const outsideButtonRef = React.createRef();
494+
const imageButtonRef = React.createRef();
494495
let button;
496+
let buttonX;
497+
let buttonY;
495498
let title;
496499

497500
function action(formData) {
498501
button = formData.get('button');
502+
buttonX = formData.get('button.x');
503+
buttonY = formData.get('button.y');
499504
title = formData.get('title');
500505
}
501506

@@ -510,6 +515,12 @@ describe('ReactDOMForm', () => {
510515
<button name="button" value="edit" ref={buttonRef}>
511516
Edit
512517
</button>
518+
<input
519+
type="image"
520+
name="button"
521+
href="/some/image.png"
522+
ref={imageButtonRef}
523+
/>
513524
</form>
514525
<form id="form" action={action}>
515526
<input type="text" name="title" defaultValue="hello" />
@@ -548,9 +559,12 @@ describe('ReactDOMForm', () => {
548559
expect(button).toBe('outside');
549560
expect(title).toBe('hello');
550561

551-
// Ensure that the type field got correctly restored
552-
expect(inputRef.current.getAttribute('type')).toBe('submit');
553-
expect(buttonRef.current.getAttribute('type')).toBe(null);
562+
await submit(imageButtonRef.current);
563+
564+
expect(button).toBe(null);
565+
expect(buttonX).toBe('0');
566+
expect(buttonY).toBe('0');
567+
expect(title).toBe('hello');
554568
});
555569

556570
it('excludes the submitter name when the submitter is a function action', async () => {

packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMForm-test.js

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -118,17 +118,7 @@ describe('ReactFlightDOMForm', () => {
118118
const method = (submitter && submitter.formMethod) || form.method;
119119
const encType = (submitter && submitter.formEnctype) || form.enctype;
120120
if (method === 'post' && encType === 'multipart/form-data') {
121-
let formData;
122-
if (submitter) {
123-
const temp = document.createElement('input');
124-
temp.name = submitter.name;
125-
temp.value = submitter.value;
126-
submitter.parentNode.insertBefore(temp, submitter);
127-
formData = new FormData(form);
128-
temp.parentNode.removeChild(temp);
129-
} else {
130-
formData = new FormData(form);
131-
}
121+
const formData = new FormData(form, submitter);
132122
return POST(formData);
133123
}
134124
throw new Error('Navigate to: ' + action);

0 commit comments

Comments
 (0)