-
Notifications
You must be signed in to change notification settings - Fork 49k
Switching checked to null should leave the current value #26667
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
f54ddcb
21a7016
4ae7d93
8a374ed
12db62b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -89,9 +89,30 @@ export function updateInput( | |
checked: ?boolean, | ||
defaultChecked: ?boolean, | ||
type: ?string, | ||
name: ?string, | ||
) { | ||
const node: HTMLInputElement = (element: any); | ||
|
||
// Temporarily disconnect the input from any radio buttons. | ||
// Changing the type or name as the same time as changing the checked value | ||
// needs to be atomically applied. We can only ensure that by disconnecting | ||
// the name while do the mutations and then reapply the name after that's done. | ||
node.name = ''; | ||
|
||
if ( | ||
type != null && | ||
typeof type !== 'function' && | ||
typeof type !== 'symbol' && | ||
typeof type !== 'boolean' | ||
) { | ||
if (__DEV__) { | ||
checkAttributeStringCoercion(type, 'type'); | ||
} | ||
node.type = type; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is always setting the type instead of only if it has changed. Not sure if that would matter like resetting dirty flags. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's fine? from the spec it sounds like it would only be the value sanitization algorithm but I tested https://codesandbox.io/s/crazy-ace-rc85uh?file=/src/App.js in chrome, safari, and firefox and none of them seem to do anything when reassigning type to the same value (you can type non-numbers like the letter |
||
} else { | ||
node.removeAttribute('type'); | ||
} | ||
|
||
if (value != null) { | ||
if (type === 'number') { | ||
if ( | ||
|
@@ -157,6 +178,20 @@ export function updateInput( | |
if (checked != null && node.checked !== !!checked) { | ||
node.checked = checked; | ||
} | ||
|
||
if ( | ||
name != null && | ||
typeof name !== 'function' && | ||
typeof name !== 'symbol' && | ||
typeof name !== 'boolean' | ||
) { | ||
if (__DEV__) { | ||
checkAttributeStringCoercion(name, 'name'); | ||
} | ||
node.name = name; | ||
} else { | ||
node.removeAttribute('name'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is it better to removeAttribute above instead of |
||
} | ||
} | ||
|
||
export function initInput( | ||
|
@@ -166,10 +201,23 @@ export function initInput( | |
checked: ?boolean, | ||
defaultChecked: ?boolean, | ||
type: ?string, | ||
name: ?string, | ||
isHydrating: boolean, | ||
) { | ||
const node: HTMLInputElement = (element: any); | ||
|
||
if ( | ||
type != null && | ||
typeof type !== 'function' && | ||
typeof type !== 'symbol' && | ||
typeof type !== 'boolean' | ||
) { | ||
if (__DEV__) { | ||
checkAttributeStringCoercion(type, 'type'); | ||
} | ||
node.type = type; | ||
} | ||
|
||
if (value != null || defaultValue != null) { | ||
const isButton = type === 'submit' || type === 'reset'; | ||
|
||
|
@@ -235,10 +283,6 @@ export function initInput( | |
// will sometimes influence the value of checked (even after detachment). | ||
// Reference: https://bugs.chromium.org/p/chromium/issues/detail?id=608416 | ||
// We need to temporarily unset name to avoid disrupting radio button groups. | ||
const name = node.name; | ||
if (name !== '') { | ||
node.name = ''; | ||
} | ||
|
||
const checkedOrDefault = checked != null ? checked : defaultChecked; | ||
// TODO: This 'function' or 'symbol' check isn't replicated in other places | ||
|
@@ -276,7 +320,16 @@ export function initInput( | |
node.defaultChecked = !!initialChecked; | ||
} | ||
|
||
if (name !== '') { | ||
// Name needs to be set at the end so that it applies atomically to connected radio buttons. | ||
if ( | ||
name != null && | ||
typeof name !== 'function' && | ||
typeof name !== 'symbol' && | ||
typeof name !== 'boolean' | ||
) { | ||
if (__DEV__) { | ||
checkAttributeStringCoercion(name, 'name'); | ||
} | ||
node.name = name; | ||
} | ||
} | ||
|
@@ -291,6 +344,7 @@ export function restoreControlledInputState(element: Element, props: Object) { | |
props.checked, | ||
props.defaultChecked, | ||
props.type, | ||
props.name, | ||
); | ||
const name = props.name; | ||
if (props.type === 'radio' && name != null) { | ||
|
@@ -347,6 +401,7 @@ export function restoreControlledInputState(element: Element, props: Object) { | |
otherProps.checked, | ||
otherProps.defaultChecked, | ||
otherProps.type, | ||
otherProps.name, | ||
); | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similarly, we didn't used to do this in the update phase - only init phase. Not sure if it'll mess with some internal states.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it should be good