From 1c4f102499ed6cc5a047806ce108929f079bc87a Mon Sep 17 00:00:00 2001 From: eps1lon Date: Wed, 11 May 2022 20:40:34 +0200 Subject: [PATCH] Match Preact behavior for boolean props on custom elements --- .../react-dom/src/client/DOMPropertyOperations.js | 13 +++++++++++++ packages/react-dom/src/client/ReactDOMComponent.js | 14 ++++++++++++-- .../src/server/ReactDOMServerFormatConfig.js | 8 +++++++- packages/react-dom/src/shared/DOMProperty.js | 5 +++++ 4 files changed, 37 insertions(+), 3 deletions(-) diff --git a/packages/react-dom/src/client/DOMPropertyOperations.js b/packages/react-dom/src/client/DOMPropertyOperations.js index f3d6fdac89795..eed5767e8a002 100644 --- a/packages/react-dom/src/client/DOMPropertyOperations.js +++ b/packages/react-dom/src/client/DOMPropertyOperations.js @@ -115,6 +115,7 @@ export function getValueForAttribute( node: Element, name: string, expected: mixed, + isCustomComponentTag: boolean, ): mixed { if (__DEV__) { if (!isAttributeNameSafe(name)) { @@ -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); } @@ -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) { diff --git a/packages/react-dom/src/client/ReactDOMComponent.js b/packages/react-dom/src/client/ReactDOMComponent.js index 75e017a451836..19eb70e583b39 100644 --- a/packages/react-dom/src/client/ReactDOMComponent.js +++ b/packages/react-dom/src/client/ReactDOMComponent.js @@ -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); @@ -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 = diff --git a/packages/react-dom/src/server/ReactDOMServerFormatConfig.js b/packages/react-dom/src/server/ReactDOMServerFormatConfig.js index 4814bd0aa3334..c8d6d35ceb6be 100644 --- a/packages/react-dom/src/server/ReactDOMServerFormatConfig.js +++ b/packages/react-dom/src/server/ReactDOMServerFormatConfig.js @@ -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; } @@ -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. diff --git a/packages/react-dom/src/shared/DOMProperty.js b/packages/react-dom/src/shared/DOMProperty.js index 278a9fd12b006..b5540debb71df 100644 --- a/packages/react-dom/src/shared/DOMProperty.js +++ b/packages/react-dom/src/shared/DOMProperty.js @@ -162,6 +162,11 @@ export function shouldRemoveAttribute( return true; } if (isCustomComponentTag) { + if (enableCustomElementPropertySupport) { + if (value === false) { + return true; + } + } return false; } if (propertyInfo !== null) {