diff --git a/packages/react-dom/src/__tests__/DOMPropertyOperations-test.js b/packages/react-dom/src/__tests__/DOMPropertyOperations-test.js index 28776b1eb6..99f92cba9b 100644 --- a/packages/react-dom/src/__tests__/DOMPropertyOperations-test.js +++ b/packages/react-dom/src/__tests__/DOMPropertyOperations-test.js @@ -504,6 +504,35 @@ describe('DOMPropertyOperations', () => { expect(customElement.foo).toBe('two'); expect(customElement.getAttribute('foo')).toBe('one'); }); + + // @gate enableCustomElementPropertySupport + it('custom element properties should accept functions', () => { + const container = document.createElement('div'); + document.body.appendChild(container); + ReactDOM.render(, container); + const customElement = container.querySelector('my-custom-element'); + + // Install a setter to activate the `in` heuristic + Object.defineProperty(customElement, 'foo', { + set: function(x) { + this._foo = x; + }, + get: function() { + return this._foo; + }, + }); + function myFunction() { + return 'this is myFunction'; + } + ReactDOM.render(, container); + expect(customElement.foo).toBe(myFunction); + + // Also remove and re-add the property for good measure + ReactDOM.render(, container); + expect(customElement.foo).toBe(null); + ReactDOM.render(, container); + expect(customElement.foo).toBe(myFunction); + }); }); describe('deleteValueForProperty', () => { diff --git a/packages/react-dom/src/client/DOMPropertyOperations.js b/packages/react-dom/src/client/DOMPropertyOperations.js index 71b53d703c..f3d6fdac89 100644 --- a/packages/react-dom/src/client/DOMPropertyOperations.js +++ b/packages/react-dom/src/client/DOMPropertyOperations.js @@ -184,10 +184,6 @@ export function setValueForProperty( } } - if (shouldRemoveAttribute(name, value, propertyInfo, isCustomComponentTag)) { - value = null; - } - if ( enableCustomElementPropertySupport && isCustomComponentTag && @@ -197,6 +193,10 @@ export function setValueForProperty( return; } + if (shouldRemoveAttribute(name, value, propertyInfo, isCustomComponentTag)) { + value = null; + } + // If the prop isn't in the special list, treat it as a simple attribute. if (isCustomComponentTag || propertyInfo === null) { if (isAttributeNameSafe(name)) {