@samitouri / QOS-React-2 / commits / a87adefecd

Allow functions to be passed to custom element setters (#23042)

This is part of the new custom element features that were implemented here: https://github.com/facebook/react/commit/24dd07bd269590ee5024b7f0f1906887d256ea86 When a custom element has a setter for a property and passes the `in` heuristic, the value passed to the react property should be assigned directly to the custom element's property, regardless of the type of the value. However, it was discovered that this isn't working with functions. This patch makes it work with functions. Fixes https://github.com/facebook/react/issues/23041

Joey Arhar committed Jan 12, 2022 at 13:12 UTC a87adefecdff672d5261e93945c227ad72c5444c
2 files changed +33 -4
packages/react-dom/src/__tests__/DOMPropertyOperations-test.js
+29
@@ -504,6 +504,35 @@ describe('DOMPropertyOperations', () => {
504 expect(customElement.foo).toBe('two');
505 expect(customElement.getAttribute('foo')).toBe('one');
506 });
507 +
508 + // @gate enableCustomElementPropertySupport
509 + it('custom element properties should accept functions', () => {
510 + const container = document.createElement('div');
511 + document.body.appendChild(container);
512 + ReactDOM.render(<my-custom-element />, container);
513 + const customElement = container.querySelector('my-custom-element');
514 +
515 + // Install a setter to activate the `in` heuristic
516 + Object.defineProperty(customElement, 'foo', {
517 + set: function(x) {
518 + this._foo = x;
519 + },
520 + get: function() {
521 + return this._foo;
522 + },
523 + });
524 + function myFunction() {
525 + return 'this is myFunction';
526 + }
527 + ReactDOM.render(<my-custom-element foo={myFunction} />, container);
528 + expect(customElement.foo).toBe(myFunction);
529 +
530 + // Also remove and re-add the property for good measure
531 + ReactDOM.render(<my-custom-element />, container);
532 + expect(customElement.foo).toBe(null);
533 + ReactDOM.render(<my-custom-element foo={myFunction} />, container);
534 + expect(customElement.foo).toBe(myFunction);
535 + });
536 });
537
538 describe('deleteValueForProperty', () => {
packages/react-dom/src/client/DOMPropertyOperations.js
+4 -4
@@ -184,10 +184,6 @@ export function setValueForProperty(
184 }
185 }
186
187 - if (shouldRemoveAttribute(name, value, propertyInfo, isCustomComponentTag)) {
188 - value = null;
189 - }
190 -
187 if (
188 enableCustomElementPropertySupport &&
189 isCustomComponentTag &&
@@ -197,6 +193,10 @@ export function setValueForProperty(
193 return;
194 }
195
196 + if (shouldRemoveAttribute(name, value, propertyInfo, isCustomComponentTag)) {
197 + value = null;
198 + }
199 +
200 // If the prop isn't in the special list, treat it as a simple attribute.
201 if (isCustomComponentTag || propertyInfo === null) {
202 if (isAttributeNameSafe(name)) {