Skip to content

Commit d1cccc0

Browse files
committed
Revert "Refactor some controlled component stuff (#26573)"
This reverts commit e5146cb.
1 parent ad3318e commit d1cccc0

File tree

11 files changed

+267
-299
lines changed

11 files changed

+267
-299
lines changed

packages/react-dom-bindings/src/client/ReactDOMComponent.js

Lines changed: 46 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
* @flow
88
*/
99

10+
import type {InputWithWrapperState} from './ReactDOMInput';
11+
1012
import {
1113
registrationNameDependencies,
1214
possibleRegistrationNames,
@@ -15,7 +17,6 @@ import {
1517
import {canUseDOM} from 'shared/ExecutionEnvironment';
1618
import {checkHtmlStringCoercion} from 'shared/CheckStringCoercion';
1719
import {checkAttributeStringCoercion} from 'shared/CheckStringCoercion';
18-
import {checkControlledValueProps} from '../shared/ReactControlledValuePropTypes';
1920

2021
import {
2122
getValueForAttribute,
@@ -26,24 +27,27 @@ import {
2627
setValueForNamespacedAttribute,
2728
} from './DOMPropertyOperations';
2829
import {
29-
validateInputProps,
30-
initInput,
31-
updateInputChecked,
32-
updateInput,
33-
restoreControlledInputState,
30+
initWrapperState as ReactDOMInputInitWrapperState,
31+
postMountWrapper as ReactDOMInputPostMountWrapper,
32+
updateChecked as ReactDOMInputUpdateChecked,
33+
updateWrapper as ReactDOMInputUpdateWrapper,
34+
restoreControlledState as ReactDOMInputRestoreControlledState,
3435
} from './ReactDOMInput';
35-
import {initOption, validateOptionProps} from './ReactDOMOption';
3636
import {
37-
validateSelectProps,
38-
initSelect,
39-
restoreControlledSelectState,
40-
updateSelect,
37+
postMountWrapper as ReactDOMOptionPostMountWrapper,
38+
validateProps as ReactDOMOptionValidateProps,
39+
} from './ReactDOMOption';
40+
import {
41+
initWrapperState as ReactDOMSelectInitWrapperState,
42+
postMountWrapper as ReactDOMSelectPostMountWrapper,
43+
restoreControlledState as ReactDOMSelectRestoreControlledState,
44+
postUpdateWrapper as ReactDOMSelectPostUpdateWrapper,
4145
} from './ReactDOMSelect';
4246
import {
43-
validateTextareaProps,
44-
initTextarea,
45-
updateTextarea,
46-
restoreControlledTextareaState,
47+
initWrapperState as ReactDOMTextareaInitWrapperState,
48+
postMountWrapper as ReactDOMTextareaPostMountWrapper,
49+
updateWrapper as ReactDOMTextareaUpdateWrapper,
50+
restoreControlledState as ReactDOMTextareaRestoreControlledState,
4751
} from './ReactDOMTextarea';
4852
import {track} from './inputValueTracking';
4953
import setInnerHTML from './setInnerHTML';
@@ -75,8 +79,6 @@ import {
7579
listenToNonDelegatedEvent,
7680
} from '../events/DOMPluginEventSystem';
7781

78-
let didWarnControlledToUncontrolled = false;
79-
let didWarnUncontrolledToControlled = false;
8082
let didWarnInvalidHydration = false;
8183
let canDiffStyleForHydrationWarning;
8284
if (__DEV__) {
@@ -803,9 +805,7 @@ export function setInitialProperties(
803805
break;
804806
}
805807
case 'input': {
806-
if (__DEV__) {
807-
checkControlledValueProps('input', props);
808-
}
808+
ReactDOMInputInitWrapperState(domElement, props);
809809
// We listen to this event in case to ensure emulated bubble
810810
// listeners still fire for the invalid event.
811811
listenToNonDelegatedEvent('invalid', domElement);
@@ -834,10 +834,10 @@ export function setInitialProperties(
834834
break;
835835
}
836836
case 'checked': {
837+
const node = ((domElement: any): InputWithWrapperState);
837838
const checked =
838-
propValue != null ? propValue : props.defaultChecked;
839-
const inputElement: HTMLInputElement = (domElement: any);
840-
inputElement.checked =
839+
propValue != null ? propValue : node._wrapperState.initialChecked;
840+
node.checked =
841841
!!checked &&
842842
typeof checked !== 'function' &&
843843
checked !== 'symbol';
@@ -866,14 +866,11 @@ export function setInitialProperties(
866866
// TODO: Make sure we check if this is still unmounted or do any clean
867867
// up necessary since we never stop tracking anymore.
868868
track((domElement: any));
869-
validateInputProps(domElement, props);
870-
initInput(domElement, props, false);
869+
ReactDOMInputPostMountWrapper(domElement, props, false);
871870
return;
872871
}
873872
case 'select': {
874-
if (__DEV__) {
875-
checkControlledValueProps('select', props);
876-
}
873+
ReactDOMSelectInitWrapperState(domElement, props);
877874
// We listen to this event in case to ensure emulated bubble
878875
// listeners still fire for the invalid event.
879876
listenToNonDelegatedEvent('invalid', domElement);
@@ -896,14 +893,11 @@ export function setInitialProperties(
896893
}
897894
}
898895
}
899-
validateSelectProps(domElement, props);
900-
initSelect(domElement, props);
896+
ReactDOMSelectPostMountWrapper(domElement, props);
901897
return;
902898
}
903899
case 'textarea': {
904-
if (__DEV__) {
905-
checkControlledValueProps('textarea', props);
906-
}
900+
ReactDOMTextareaInitWrapperState(domElement, props);
907901
// We listen to this event in case to ensure emulated bubble
908902
// listeners still fire for the invalid event.
909903
listenToNonDelegatedEvent('invalid', domElement);
@@ -942,12 +936,11 @@ export function setInitialProperties(
942936
// TODO: Make sure we check if this is still unmounted or do any clean
943937
// up necessary since we never stop tracking anymore.
944938
track((domElement: any));
945-
validateTextareaProps(domElement, props);
946-
initTextarea(domElement, props);
939+
ReactDOMTextareaPostMountWrapper(domElement, props);
947940
return;
948941
}
949942
case 'option': {
950-
validateOptionProps(domElement, props);
943+
ReactDOMOptionValidateProps(domElement, props);
951944
for (const propKey in props) {
952945
if (!props.hasOwnProperty(propKey)) {
953946
continue;
@@ -970,7 +963,7 @@ export function setInitialProperties(
970963
}
971964
}
972965
}
973-
initOption(domElement, props);
966+
ReactDOMOptionPostMountWrapper(domElement, props);
974967
return;
975968
}
976969
case 'dialog': {
@@ -1220,17 +1213,17 @@ export function updateProperties(
12201213
// In the middle of an update, it is possible to have multiple checked.
12211214
// When a checked radio tries to change name, browser makes another radio's checked false.
12221215
if (nextProps.type === 'radio' && nextProps.name != null) {
1223-
updateInputChecked(domElement, nextProps);
1216+
ReactDOMInputUpdateChecked(domElement, nextProps);
12241217
}
12251218
for (let i = 0; i < updatePayload.length; i += 2) {
12261219
const propKey = updatePayload[i];
12271220
const propValue = updatePayload[i + 1];
12281221
switch (propKey) {
12291222
case 'checked': {
1223+
const node = ((domElement: any): InputWithWrapperState);
12301224
const checked =
1231-
propValue != null ? propValue : nextProps.defaultChecked;
1232-
const inputElement: HTMLInputElement = (domElement: any);
1233-
inputElement.checked =
1225+
propValue != null ? propValue : node._wrapperState.initialChecked;
1226+
node.checked =
12341227
!!checked &&
12351228
typeof checked !== 'function' &&
12361229
checked !== 'symbol';
@@ -1256,50 +1249,10 @@ export function updateProperties(
12561249
}
12571250
}
12581251
}
1259-
1260-
if (__DEV__) {
1261-
const wasControlled =
1262-
lastProps.type === 'checkbox' || lastProps.type === 'radio'
1263-
? lastProps.checked != null
1264-
: lastProps.value != null;
1265-
const isControlled =
1266-
nextProps.type === 'checkbox' || nextProps.type === 'radio'
1267-
? nextProps.checked != null
1268-
: nextProps.value != null;
1269-
1270-
if (
1271-
!wasControlled &&
1272-
isControlled &&
1273-
!didWarnUncontrolledToControlled
1274-
) {
1275-
console.error(
1276-
'A component is changing an uncontrolled input to be controlled. ' +
1277-
'This is likely caused by the value changing from undefined to ' +
1278-
'a defined value, which should not happen. ' +
1279-
'Decide between using a controlled or uncontrolled input ' +
1280-
'element for the lifetime of the component. More info: https://reactjs.org/link/controlled-components',
1281-
);
1282-
didWarnUncontrolledToControlled = true;
1283-
}
1284-
if (
1285-
wasControlled &&
1286-
!isControlled &&
1287-
!didWarnControlledToUncontrolled
1288-
) {
1289-
console.error(
1290-
'A component is changing a controlled input to be uncontrolled. ' +
1291-
'This is likely caused by the value changing from a defined to ' +
1292-
'undefined, which should not happen. ' +
1293-
'Decide between using a controlled or uncontrolled input ' +
1294-
'element for the lifetime of the component. More info: https://reactjs.org/link/controlled-components',
1295-
);
1296-
didWarnControlledToUncontrolled = true;
1297-
}
1298-
}
12991252
// Update the wrapper around inputs *after* updating props. This has to
13001253
// happen after updating the rest of props. Otherwise HTML5 input validations
13011254
// raise warnings and prevent the new value from being assigned.
1302-
updateInput(domElement, nextProps);
1255+
ReactDOMInputUpdateWrapper(domElement, nextProps);
13031256
return;
13041257
}
13051258
case 'select': {
@@ -1319,7 +1272,7 @@ export function updateProperties(
13191272
}
13201273
// <select> value update needs to occur after <option> children
13211274
// reconciliation
1322-
updateSelect(domElement, lastProps, nextProps);
1275+
ReactDOMSelectPostUpdateWrapper(domElement, nextProps);
13231276
return;
13241277
}
13251278
case 'textarea': {
@@ -1350,7 +1303,7 @@ export function updateProperties(
13501303
}
13511304
}
13521305
}
1353-
updateTextarea(domElement, nextProps);
1306+
ReactDOMTextareaUpdateWrapper(domElement, nextProps);
13541307
return;
13551308
}
13561309
case 'option': {
@@ -2310,47 +2263,38 @@ export function diffHydratedProperties(
23102263
listenToNonDelegatedEvent('toggle', domElement);
23112264
break;
23122265
case 'input':
2313-
if (__DEV__) {
2314-
checkControlledValueProps('input', props);
2315-
}
2266+
ReactDOMInputInitWrapperState(domElement, props);
23162267
// We listen to this event in case to ensure emulated bubble
23172268
// listeners still fire for the invalid event.
23182269
listenToNonDelegatedEvent('invalid', domElement);
23192270
// TODO: Make sure we check if this is still unmounted or do any clean
23202271
// up necessary since we never stop tracking anymore.
23212272
track((domElement: any));
2322-
validateInputProps(domElement, props);
23232273
// For input and textarea we current always set the value property at
23242274
// post mount to force it to diverge from attributes. However, for
23252275
// option and select we don't quite do the same thing and select
23262276
// is not resilient to the DOM state changing so we don't do that here.
23272277
// TODO: Consider not doing this for input and textarea.
2328-
initInput(domElement, props, true);
2278+
ReactDOMInputPostMountWrapper(domElement, props, true);
23292279
break;
23302280
case 'option':
2331-
validateOptionProps(domElement, props);
2281+
ReactDOMOptionValidateProps(domElement, props);
23322282
break;
23332283
case 'select':
2334-
if (__DEV__) {
2335-
checkControlledValueProps('select', props);
2336-
}
2284+
ReactDOMSelectInitWrapperState(domElement, props);
23372285
// We listen to this event in case to ensure emulated bubble
23382286
// listeners still fire for the invalid event.
23392287
listenToNonDelegatedEvent('invalid', domElement);
2340-
validateSelectProps(domElement, props);
23412288
break;
23422289
case 'textarea':
2343-
if (__DEV__) {
2344-
checkControlledValueProps('textarea', props);
2345-
}
2290+
ReactDOMTextareaInitWrapperState(domElement, props);
23462291
// We listen to this event in case to ensure emulated bubble
23472292
// listeners still fire for the invalid event.
23482293
listenToNonDelegatedEvent('invalid', domElement);
23492294
// TODO: Make sure we check if this is still unmounted or do any clean
23502295
// up necessary since we never stop tracking anymore.
23512296
track((domElement: any));
2352-
validateTextareaProps(domElement, props);
2353-
initTextarea(domElement, props);
2297+
ReactDOMTextareaPostMountWrapper(domElement, props);
23542298
break;
23552299
}
23562300

@@ -2528,13 +2472,13 @@ export function restoreControlledState(
25282472
): void {
25292473
switch (tag) {
25302474
case 'input':
2531-
restoreControlledInputState(domElement, props);
2475+
ReactDOMInputRestoreControlledState(domElement, props);
25322476
return;
25332477
case 'textarea':
2534-
restoreControlledTextareaState(domElement, props);
2478+
ReactDOMTextareaRestoreControlledState(domElement, props);
25352479
return;
25362480
case 'select':
2537-
restoreControlledSelectState(domElement, props);
2481+
ReactDOMSelectRestoreControlledState(domElement, props);
25382482
return;
25392483
}
25402484
}

0 commit comments

Comments
 (0)