Skip to content

Commit

Permalink
Match Preact behavior for boolean props on custom elements
Browse files Browse the repository at this point in the history
  • Loading branch information
eps1lon committed May 11, 2022
1 parent 1a617a4 commit 1c4f102
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 3 deletions.
13 changes: 13 additions & 0 deletions packages/react-dom/src/client/DOMPropertyOperations.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ export function getValueForAttribute(
node: Element,
name: string,
expected: mixed,
isCustomComponentTag: boolean,
): mixed {
if (__DEV__) {
if (!isAttributeNameSafe(name)) {
Expand All @@ -124,6 +125,13 @@ export function getValueForAttribute(
return expected === undefined ? undefined : null;
}
const value = node.getAttribute(name);

if (enableCustomElementPropertySupport) {
if (isCustomComponentTag && value === '') {
return true;
}
}

if (__DEV__) {
checkAttributeStringCoercion(expected, name);
}
Expand Down Expand Up @@ -196,6 +204,11 @@ export function setValueForProperty(
if (shouldRemoveAttribute(name, value, propertyInfo, isCustomComponentTag)) {
value = null;
}
if (enableCustomElementPropertySupport) {
if (isCustomComponentTag && value === true) {
value = '';
}
}

// If the prop isn't in the special list, treat it as a simple attribute.
if (isCustomComponentTag || propertyInfo === null) {
Expand Down
14 changes: 12 additions & 2 deletions packages/react-dom/src/client/ReactDOMComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -1081,7 +1081,12 @@ export function diffHydratedProperties(
} else if (isCustomComponentTag && !enableCustomElementPropertySupport) {
// $FlowFixMe - Should be inferred as not undefined.
extraAttributeNames.delete(propKey.toLowerCase());
serverValue = getValueForAttribute(domElement, propKey, nextProp);
serverValue = getValueForAttribute(
domElement,
propKey,
nextProp,
isCustomComponentTag,
);

if (nextProp !== serverValue) {
warnForPropDifference(propKey, serverValue, nextProp);
Expand Down Expand Up @@ -1128,7 +1133,12 @@ export function diffHydratedProperties(
// $FlowFixMe - Should be inferred as not undefined.
extraAttributeNames.delete(propKey);
}
serverValue = getValueForAttribute(domElement, propKey, nextProp);
serverValue = getValueForAttribute(
domElement,
propKey,
nextProp,
isCustomComponentTag,
);
}

const dontWarnCustomElement =
Expand Down
8 changes: 7 additions & 1 deletion packages/react-dom/src/server/ReactDOMServerFormatConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -1156,7 +1156,7 @@ function pushStartCustomElement(
let innerHTML = null;
for (let propKey in props) {
if (hasOwnProperty.call(props, propKey)) {
const propValue = props[propKey];
let propValue = props[propKey];
if (propValue == null) {
continue;
}
Expand All @@ -1169,6 +1169,12 @@ function pushStartCustomElement(
// so skip it.
continue;
}
if (enableCustomElementPropertySupport && propValue === false) {
continue;
}
if (enableCustomElementPropertySupport && propValue === true) {
propValue = '';
}
if (enableCustomElementPropertySupport && propKey === 'className') {
// className gets rendered as class on the client, so it should be
// rendered as class on the server.
Expand Down
5 changes: 5 additions & 0 deletions packages/react-dom/src/shared/DOMProperty.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,11 @@ export function shouldRemoveAttribute(
return true;
}
if (isCustomComponentTag) {
if (enableCustomElementPropertySupport) {
if (value === false) {
return true;
}
}
return false;
}
if (propertyInfo !== null) {
Expand Down

0 comments on commit 1c4f102

Please sign in to comment.