diff --git a/packages/react-dom-bindings/src/client/ReactDOMComponent.js b/packages/react-dom-bindings/src/client/ReactDOMComponent.js index 91bab1c90f..e2ba29ceb3 100644 --- a/packages/react-dom-bindings/src/client/ReactDOMComponent.js +++ b/packages/react-dom-bindings/src/client/ReactDOMComponent.js @@ -32,7 +32,7 @@ import { updateInput, restoreControlledInputState, } from './ReactDOMInput'; -import {validateOptionProps} from './ReactDOMOption'; +import {initOption, validateOptionProps} from './ReactDOMOption'; import { validateSelectProps, initSelect, @@ -995,6 +995,7 @@ export function setInitialProperties( } } } + initOption(domElement, props); return; } case 'dialog': { diff --git a/packages/react-dom-bindings/src/client/ReactDOMOption.js b/packages/react-dom-bindings/src/client/ReactDOMOption.js index 4f7d3105a8..7907609ad8 100644 --- a/packages/react-dom-bindings/src/client/ReactDOMOption.js +++ b/packages/react-dom-bindings/src/client/ReactDOMOption.js @@ -8,6 +8,7 @@ */ import {Children} from 'react'; +import {getToStringValue, toString} from './ToStringValue'; let didWarnSelectedSetOnOption = false; let didWarnInvalidChild = false; @@ -58,3 +59,10 @@ export function validateOptionProps(element: Element, props: Object) { } } } + +export function initOption(element: Element, props: Object) { + // value="" should make a value attribute (#6219) + if (props.value != null) { + element.setAttribute('value', toString(getToStringValue(props.value))); + } +} diff --git a/packages/react-dom/src/__tests__/ReactDOMSelect-test.js b/packages/react-dom/src/__tests__/ReactDOMSelect-test.js index 9037028b9f..901d20f8c2 100644 --- a/packages/react-dom/src/__tests__/ReactDOMSelect-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMSelect-test.js @@ -9,13 +9,6 @@ 'use strict'; -// Fix JSDOM. setAttribute is supposed to throw on things that can't be implicitly toStringed. -const setAttribute = Element.prototype.setAttribute; -Element.prototype.setAttribute = function (name, value) { - // eslint-disable-next-line react-internal/safe-string-coercion - return setAttribute.call(this, name, '' + value); -}; - describe('ReactDOMSelect', () => { let React; let ReactDOM; @@ -856,7 +849,7 @@ describe('ReactDOMSelect', () => { }); describe('When given a Symbol value', () => { - it('treats initial Symbol value as missing', () => { + it('treats initial Symbol value as an empty string', () => { let node; expect(() => { @@ -869,10 +862,10 @@ describe('ReactDOMSelect', () => { ); }).toErrorDev('Invalid value for prop `value`'); - expect(node.value).toBe('A Symbol!'); + expect(node.value).toBe(''); }); - it('treats updated Symbol value as missing', () => { + it('treats updated Symbol value as an empty string', () => { let node; expect(() => { @@ -895,7 +888,7 @@ describe('ReactDOMSelect', () => { , ); - expect(node.value).toBe('A Symbol!'); + expect(node.value).toBe(''); }); it('treats initial Symbol defaultValue as an empty string', () => { @@ -911,7 +904,7 @@ describe('ReactDOMSelect', () => { ); }).toErrorDev('Invalid value for prop `value`'); - expect(node.value).toBe('A Symbol!'); + expect(node.value).toBe(''); }); it('treats updated Symbol defaultValue as an empty string', () => { @@ -937,12 +930,12 @@ describe('ReactDOMSelect', () => { , ); - expect(node.value).toBe('A Symbol!'); + expect(node.value).toBe(''); }); }); describe('When given a function value', () => { - it('treats initial function value as missing', () => { + it('treats initial function value as an empty string', () => { let node; expect(() => { @@ -955,7 +948,7 @@ describe('ReactDOMSelect', () => { ); }).toErrorDev('Invalid value for prop `value`'); - expect(node.value).toBe('A function!'); + expect(node.value).toBe(''); }); it('treats initial function defaultValue as an empty string', () => { @@ -971,7 +964,7 @@ describe('ReactDOMSelect', () => { ); }).toErrorDev('Invalid value for prop `value`'); - expect(node.value).toBe('A function!'); + expect(node.value).toBe(''); }); it('treats updated function value as an empty string', () => { @@ -997,7 +990,7 @@ describe('ReactDOMSelect', () => { , ); - expect(node.value).toBe('A function!'); + expect(node.value).toBe(''); }); it('treats updated function defaultValue as an empty string', () => { @@ -1023,7 +1016,7 @@ describe('ReactDOMSelect', () => { , ); - expect(node.value).toBe('A function!'); + expect(node.value).toBe(''); }); });