@samitouri / QOS-React / commits / 8aeea5afa2

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