Skip to content
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

Do not assign node.value on input creation if no change will occur #12925

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
23 changes: 19 additions & 4 deletions fixtures/dom/src/components/fixtures/text-inputs/index.js
Expand Up @@ -64,21 +64,36 @@ class TextInputFixtures extends React.Component {
<Fixture>
<form className="control-box">
<fieldset>
<legend>Text</legend>
<legend>Empty value prop string</legend>
<input value="" required={true} />
</fieldset>
<fieldset>
<legend>No value prop</legend>
<input required={true} />
</fieldset>
<fieldset>
<legend>Date</legend>
<legend>Empty defaultValue prop string</legend>
<input required={true} defaultValue="" />
</fieldset>
<fieldset>
<legend>No value prop date input</legend>
<input type="date" required={true} />
</fieldset>
<fieldset>
<legend>Empty value prop date input</legend>
<input type="date" value="" required={true} />
</fieldset>
</form>
</Fixture>

<p className="footnote">
Checking the date type is also important because of a prior fix for
iOS Safari that involved assigning over value/defaultValue
properties of the input to prevent a display bug. This also
triggered input validation.
properties of the input to prevent a display bug. This also triggers
input validation.
</p>
<p className="footnote">
The date inputs should be blank in iOS. This is not a bug.
</p>
</TestCase>

Expand Down
14 changes: 11 additions & 3 deletions packages/react-dom/src/client/ReactDOMFiberInput.js
Expand Up @@ -209,16 +209,24 @@ export function postMountWrapper(element: Element, props: Object) {
const node = ((element: any): InputWithWrapperState);

if (props.hasOwnProperty('value') || props.hasOwnProperty('defaultValue')) {
const initialValue = '' + node._wrapperState.initialValue;
const currentValue = node.value;

// Do not assign value if it is already set. This prevents user text input
// from being lost during SSR hydration.
if (node.value === '') {
node.value = '' + node._wrapperState.initialValue;
if (currentValue === '') {
// Do not re-assign the value property if there is no change. This
// potentially avoids a DOM write and prevents Firefox (~60.0.1) from
// prematurely marking required inputs as invalid
if (initialValue !== currentValue) {
node.value = initialValue;
}
}

// value must be assigned before defaultValue. This fixes an issue where the
// visually displayed value of date inputs disappears on mobile Safari and Chrome:
// https://github.com/facebook/react/issues/7233
node.defaultValue = '' + node._wrapperState.initialValue;
node.defaultValue = initialValue;
}

// Normally, we'd just do `node.checked = node.checked` upon initial mount, less this bug
Expand Down