Set the correct initial value on input range (#12939)
* Set the correct initial value on input range * Add description and update value diff check for input range * add isHydrating argument and tests * update node value according to isHydrating
Maxime Nory committed
May 31, 2018 at 23:23 UTC
36546b5137e9012ebdc62fc9ec11e3518c9e0aab
3 files changed
+36
-6
packages/react-dom/src/__tests__/ReactDOMServerIntegrationForms-test.js
+28
-2
@@ -348,9 +348,13 @@ describe('ReactDOMServerIntegration', () => {
348
ControlledSelect;
349
beforeEach(() => {
350
ControlledInput = class extends React.Component {
351
+ static defaultProps = {
352
+ type: 'text',
353
+ initialValue: 'Hello',
354
+ };
355
constructor() {
352
- super();
353
- this.state = {value: 'Hello'};
356
+ super(...arguments);
357
+ this.state = {value: this.props.initialValue};
358
}
359
handleChange(event) {
360
if (this.props.onChange) {
@@ -361,6 +365,7 @@ describe('ReactDOMServerIntegration', () => {
365
render() {
366
return (
367
<input
368
+ type={this.props.type}
369
value={this.state.value}
370
onChange={this.handleChange.bind(this)}
371
/>
@@ -551,6 +556,27 @@ describe('ReactDOMServerIntegration', () => {
556
expect(changeCount).toBe(0);
557
});
558
559
+ it('should not blow away user-interaction on successful reconnect to an uncontrolled range input', () =>
560
+ testUserInteractionBeforeClientRender(
561
+ <input type="text" defaultValue="0.5" />,
562
+ '0.5',
563
+ '1',
564
+ ));
565
+
566
+ it('should not blow away user-interaction on successful reconnect to a controlled range input', async () => {
567
+ let changeCount = 0;
568
+ await testUserInteractionBeforeClientRender(
569
+ <ControlledInput
570
+ type="range"
571
+ initialValue="0.25"
572
+ onChange={() => changeCount++}
573
+ />,
574
+ '0.25',
575
+ '1',
576
+ );
577
+ expect(changeCount).toBe(0);
578
+ });
579
+
580
it('should not blow away user-entered text on successful reconnect to an uncontrolled checkbox', () =>
581
testUserInteractionBeforeClientRender(
582
<input type="checkbox" defaultChecked={true} />,
packages/react-dom/src/client/ReactDOMFiberComponent.js
+2
-2
@@ -530,7 +530,7 @@ export function setInitialProperties(
530
// TODO: Make sure we check if this is still unmounted or do any clean
531
// up necessary since we never stop tracking anymore.
532
inputValueTracking.track((domElement: any));
533
- ReactDOMFiberInput.postMountWrapper(domElement, rawProps);
533
+ ReactDOMFiberInput.postMountWrapper(domElement, rawProps, false);
534
break;
535
case 'textarea':
536
// TODO: Make sure we check if this is still unmounted or do any clean
@@ -1077,7 +1077,7 @@ export function diffHydratedProperties(
1077
// TODO: Make sure we check if this is still unmounted or do any clean
1078
// up necessary since we never stop tracking anymore.
1079
inputValueTracking.track((domElement: any));
1080
- ReactDOMFiberInput.postMountWrapper(domElement, rawProps);
1080
+ ReactDOMFiberInput.postMountWrapper(domElement, rawProps, true);
1081
break;
1082
case 'textarea':
1083
// TODO: Make sure we check if this is still unmounted or do any clean
packages/react-dom/src/client/ReactDOMFiberInput.js
+6
-2
@@ -205,7 +205,11 @@ export function updateWrapper(element: Element, props: Object) {
205
}
206
}
207
208
-export function postMountWrapper(element: Element, props: Object) {
208
+export function postMountWrapper(
209
+ element: Element,
210
+ props: Object,
211
+ isHydrating: boolean,
212
+) {
213
const node = ((element: any): InputWithWrapperState);
214
215
if (props.hasOwnProperty('value') || props.hasOwnProperty('defaultValue')) {
@@ -214,7 +218,7 @@ export function postMountWrapper(element: Element, props: Object) {
218
219
// Do not assign value if it is already set. This prevents user text input
220
// from being lost during SSR hydration.
217
- if (currentValue === '') {
221
+ if (!isHydrating) {
222
// Do not re-assign the value property if there is no change. This
223
// potentially avoids a DOM write and prevents Firefox (~60.0.1) from
224
// prematurely marking required inputs as invalid