Do not assign node.value on input creation if no change will occur (#12925)
This commit fixes an issue where assigning an empty string to required text inputs triggers the invalid state in Firefox (~60.0.1). It does this by first comparing the initial state value to the current value property on the text element. This: 1. Prevents the validation issue 2. Avoids an extra DOM Mutation in some cases
Nathan Hunzaker committed
May 29, 2018 at 09:48 UTC
8aeea5afa2d688968545b1cc5a30a48ddc0fa503
2 files changed
+30
-7
fixtures/dom/src/components/fixtures/text-inputs/index.js
+19
-4
@@ -64,21 +64,36 @@ class TextInputFixtures extends React.Component {
64
<Fixture>
65
<form className="control-box">
66
<fieldset>
67
- <legend>Text</legend>
67
+ <legend>Empty value prop string</legend>
68
+ <input value="" required={true} />
69
+ </fieldset>
70
+ <fieldset>
71
+ <legend>No value prop</legend>
72
<input required={true} />
73
</fieldset>
74
<fieldset>
71
- <legend>Date</legend>
75
+ <legend>Empty defaultValue prop string</legend>
76
+ <input required={true} defaultValue="" />
77
+ </fieldset>
78
+ <fieldset>
79
+ <legend>No value prop date input</legend>
80
<input type="date" required={true} />
81
</fieldset>
82
+ <fieldset>
83
+ <legend>Empty value prop date input</legend>
84
+ <input type="date" value="" required={true} />
85
+ </fieldset>
86
</form>
87
</Fixture>
88
89
<p className="footnote">
90
Checking the date type is also important because of a prior fix for
91
iOS Safari that involved assigning over value/defaultValue
80
- properties of the input to prevent a display bug. This also
81
- triggered input validation.
92
+ properties of the input to prevent a display bug. This also triggers
93
+ input validation.
94
+ </p>
95
+ <p className="footnote">
96
+ The date inputs should be blank in iOS. This is not a bug.
97
</p>
98
</TestCase>
99
packages/react-dom/src/client/ReactDOMFiberInput.js
+11
-3
@@ -209,16 +209,24 @@ export function postMountWrapper(element: Element, props: Object) {
209
const node = ((element: any): InputWithWrapperState);
210
211
if (props.hasOwnProperty('value') || props.hasOwnProperty('defaultValue')) {
212
+ const initialValue = '' + node._wrapperState.initialValue;
213
+ const currentValue = node.value;
214
+
215
// Do not assign value if it is already set. This prevents user text input
216
// from being lost during SSR hydration.
214
- if (node.value === '') {
215
- node.value = '' + node._wrapperState.initialValue;
217
+ if (currentValue === '') {
218
+ // Do not re-assign the value property if there is no change. This
219
+ // potentially avoids a DOM write and prevents Firefox (~60.0.1) from
220
+ // prematurely marking required inputs as invalid
221
+ if (initialValue !== currentValue) {
222
+ node.value = initialValue;
223
+ }
224
}
225
226
// value must be assigned before defaultValue. This fixes an issue where the
227
// visually displayed value of date inputs disappears on mobile Safari and Chrome:
228
// https://github.com/facebook/react/issues/7233
221
- node.defaultValue = '' + node._wrapperState.initialValue;
229
+ node.defaultValue = initialValue;
230
}
231
232
// Normally, we'd just do `node.checked = node.checked` upon initial mount, less this bug