Skip to content

Commit

Permalink
Compare name when hydrating hidden fields to filter out extra form ac…
Browse files Browse the repository at this point in the history
…tion fields
  • Loading branch information
sebmarkbage committed May 25, 2023
1 parent 6fc3333 commit 7a054c9
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 5 deletions.
18 changes: 14 additions & 4 deletions packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js
Original file line number Diff line number Diff line change
Expand Up @@ -1068,11 +1068,21 @@ export function canHydrateInstance(
if (
enableFormActions &&
type === 'input' &&
(element: any).type === 'hidden' &&
anyProps.type !== 'hidden'
(element: any).type === 'hidden'
) {
// Skip past hidden inputs unless that's what we're looking for. This allows us
// embed extra form data in the original form.
if (__DEV__) {
checkAttributeStringCoercion(anyProps.name, 'name');
}
const name = anyProps.name == null ? null : '' + anyProps.name;
if (
anyProps.type !== 'hidden' ||
element.getAttribute('name') !== name
) {
// Skip past hidden inputs unless that's what we're looking for. This allows us
// embed extra form data in the original form.
} else {
return element;
}
} else {
return element;
}
Expand Down
52 changes: 51 additions & 1 deletion packages/react-dom/src/__tests__/ReactDOMFizzForm-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,7 @@ describe('ReactDOMFizzForm', () => {

// @gate enableFormActions
it('can provide a custom action on buttons the server for actions', async () => {
const hiddenRef = React.createRef();
const inputRef = React.createRef();
const buttonRef = React.createRef();
let foo;
Expand All @@ -546,7 +547,7 @@ describe('ReactDOMFizzForm', () => {
function App() {
return (
<form>
<input type="hidden" name="foo" value="bar" />
<input type="hidden" name="foo" value="bar" ref={hiddenRef} />
<input
type="submit"
formAction={action}
Expand Down Expand Up @@ -588,6 +589,8 @@ describe('ReactDOMFizzForm', () => {
ReactDOMClient.hydrateRoot(container, <App />);
});

expect(hiddenRef.current.name).toBe('foo');

submit(inputRef.current);

expect(foo).toBe('bar');
Expand All @@ -598,4 +601,51 @@ describe('ReactDOMFizzForm', () => {

expect(foo).toBe('bar');
});

// @gate enableFormActions
it('can hydrate hidden fields in the beginning of a form', async () => {
const hiddenRef = React.createRef();

let invoked = false;
function action(formData) {
invoked = true;
}
action.$$FORM_ACTION = function (identifierPrefix) {
const extraFields = new FormData();
extraFields.append(identifierPrefix + 'hello', 'world');
return {
action: '',
name: identifierPrefix,
method: 'POST',
encType: 'multipart/form-data',
data: extraFields,
};
};
function App() {
return (
<form action={action}>
<input type="hidden" name="bar" defaultValue="baz" ref={hiddenRef} />
<input type="text" name="foo" defaultValue="bar" />
</form>
);
}

const stream = await ReactDOMServer.renderToReadableStream(<App />);
await readIntoContainer(stream);

const barField = container.querySelector('[name=bar]');

await act(async () => {
ReactDOMClient.hydrateRoot(container, <App />);
});

expect(hiddenRef.current).toBe(barField);

expect(hiddenRef.current.name).toBe('bar');
expect(hiddenRef.current.value).toBe('baz');

expect(container.querySelectorAll('[name=bar]').length).toBe(1);

submit(hiddenRef.current.form);
});
});

0 comments on commit 7a054c9

Please sign in to comment.