From ab5fe174c69ea4ea5019390f4234a83ef7ce8d52 Mon Sep 17 00:00:00 2001 From: Mateusz Date: Thu, 14 Mar 2019 22:40:09 +0100 Subject: [PATCH] Don't set the first option as selected in select tag with `size` attribute (#14242) * Set 'size' attribute to select tag if it occurs before appending options * Add comment about why size is assigned on select create. Tests I added some more clarification for why size must be set on select element creation: - In the source code - In the DOM test fixture - In a unit test * Use let, not const in select tag stub assignment --- .../src/components/fixtures/selects/index.js | 28 +++++++++++++++++++ .../src/__tests__/ReactDOMSelect-test.js | 26 +++++++++++++++++ .../react-dom/src/client/ReactDOMComponent.js | 23 +++++++++++---- 3 files changed, 71 insertions(+), 6 deletions(-) diff --git a/fixtures/dom/src/components/fixtures/selects/index.js b/fixtures/dom/src/components/fixtures/selects/index.js index e83bc3efd667..c0423b6df853 100644 --- a/fixtures/dom/src/components/fixtures/selects/index.js +++ b/fixtures/dom/src/components/fixtures/selects/index.js @@ -202,6 +202,34 @@ class SelectFixture extends React.Component { + + + + No options should be selected. + + +
+ +
+ +

+ Notes: This happens if size is assigned after + options are selected. The select element picks the first item by + default, then it is expanded to show more options when{' '} + size is assigned, preserving the default selection. +

+

+ This was introduced in React 16.0.0 when options were added before + select attribute assignment. +

+
); } diff --git a/packages/react-dom/src/__tests__/ReactDOMSelect-test.js b/packages/react-dom/src/__tests__/ReactDOMSelect-test.js index bd87c4543e95..cc7285d155ac 100644 --- a/packages/react-dom/src/__tests__/ReactDOMSelect-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMSelect-test.js @@ -362,6 +362,32 @@ describe('ReactDOMSelect', () => { expect(node.options[2].selected).toBe(true); // gorilla }); + it('does not select an item when size is initially set to greater than 1', () => { + const stub = ( + + ); + const container = document.createElement('div'); + const select = ReactDOM.render(stub, container); + + expect(select.options[0].selected).toBe(false); + expect(select.options[1].selected).toBe(false); + expect(select.options[2].selected).toBe(false); + + // Note: There is an inconsistency between JSDOM and Chrome where + // Chrome reports an empty string when no value is selected for a + // single-select with a size greater than 0. JSDOM reports the first + // value + // + // This assertion exists only for clarity of JSDOM behavior: + expect(select.value).toBe('monkey'); // "" in Chrome + // Despite this, the selection index is correct: + expect(select.selectedIndex).toBe(-1); + }); + it('should remember value when switching to uncontrolled', () => { let stub = (