Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 33 additions & 9 deletions packages/react-dom/src/server/ReactDOMServerFormatConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -810,6 +810,11 @@ function pushInput(

target.push(startChunkForTag('input'));

let value = null;
let defaultValue = null;
let checked = null;
let defaultChecked = null;

for (const propKey in props) {
if (hasOwnProperty.call(props, propKey)) {
const propValue = props[propKey];
Expand All @@ -827,21 +832,35 @@ function pushInput(
);
// eslint-disable-next-line-no-fallthrough
case 'defaultChecked':
// Previously "checked" would win but now it's enumeration order dependent.
// There's a warning in either case.
pushAttribute(target, responseState, 'checked', propValue);
defaultChecked = propValue;
break;
case 'defaultValue':
// Previously "value" would win but now it's enumeration order dependent.
// There's a warning in either case.
pushAttribute(target, responseState, 'value', propValue);
defaultValue = propValue;
break;
case 'checked':
checked = propValue;
break;
case 'value':
value = propValue;
break;
default:
pushAttribute(target, responseState, propKey, propValue);
break;
}
}
}

if (checked !== null) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this instead of props.checked? Well because we have to do the loop and check every property name anyway. Where as props.checked likely wouldn't be fast pathed since the hidden class of these props are often different. So it would be an unnecessary map look up. However, I do a props.id check below but that's just because I expect that code path to go away.

pushAttribute(target, responseState, 'checked', checked);
} else if (defaultChecked !== null) {
pushAttribute(target, responseState, 'checked', defaultChecked);
}
if (value !== null) {
pushAttribute(target, responseState, 'value', value);
} else if (defaultValue !== null) {
pushAttribute(target, responseState, 'value', defaultValue);
}

if (assignID !== null) {
pushID(target, responseState, assignID, props.id);
}
Expand Down Expand Up @@ -877,6 +896,7 @@ function pushStartTextArea(
target.push(startChunkForTag('textarea'));

let value = null;
let defaultValue = null;
let children = null;
for (const propKey in props) {
if (hasOwnProperty.call(props, propKey)) {
Expand All @@ -889,11 +909,11 @@ function pushStartTextArea(
children = propValue;
break;
case 'value':
case 'defaultValue':
// Previously "checked" would win but now it's enumeration order dependent.
// There's a warning in either case.
value = propValue;
break;
case 'defaultValue':
defaultValue = propValue;
break;
case 'dangerouslySetInnerHTML':
invariant(
false,
Expand All @@ -906,6 +926,10 @@ function pushStartTextArea(
}
}
}
if (value === null && defaultValue !== null) {
value = defaultValue;
}

if (assignID !== null) {
pushID(target, responseState, assignID, props.id);
}
Expand Down