allow to ignore value attribute for option (#5362)
yiminghe committed
May 10, 2016 at 00:22 UTC
904ee9a6787d74fcffcbf1ceece1c69a9014604d
2 files changed
+58
-32
src/renderers/dom/client/wrappers/ReactDOMOption.js
+33
-19
@@ -16,6 +16,30 @@ var ReactDOMComponentTree = require('ReactDOMComponentTree');
16
var ReactDOMSelect = require('ReactDOMSelect');
17
18
var warning = require('warning');
19
+var didWarnInvalidOptionChildren = false;
20
+
21
+function flattenChildren(children) {
22
+ var content = '';
23
+
24
+ // Flatten children and warn if they aren't strings or numbers;
25
+ // invalid types are ignored.
26
+ ReactChildren.forEach(children, function(child) {
27
+ if (child == null) {
28
+ return;
29
+ }
30
+ if (typeof child === 'string' || typeof child === 'number') {
31
+ content += child;
32
+ } else if (!didWarnInvalidOptionChildren) {
33
+ didWarnInvalidOptionChildren = true;
34
+ warning(
35
+ false,
36
+ 'Only strings and numbers are supported as <option> children.'
37
+ );
38
+ }
39
+ });
40
+
41
+ return content;
42
+}
43
44
/**
45
* Implements an <option> native component that warns when `selected` is set.
@@ -49,17 +73,23 @@ var ReactDOMOption = {
73
// or missing (e.g., for <datalist>), we don't change props.selected
74
var selected = null;
75
if (selectValue != null) {
76
+ var value;
77
+ if (props.value != null) {
78
+ value = props.value + '';
79
+ } else {
80
+ value = flattenChildren(props.children);
81
+ }
82
selected = false;
83
if (Array.isArray(selectValue)) {
84
// multiple
85
for (var i = 0; i < selectValue.length; i++) {
56
- if ('' + selectValue[i] === '' + props.value) {
86
+ if ('' + selectValue[i] === value) {
87
selected = true;
88
break;
89
}
90
}
91
} else {
62
- selected = ('' + selectValue === '' + props.value);
92
+ selected = ('' + selectValue === value);
93
}
94
}
95
@@ -84,23 +114,7 @@ var ReactDOMOption = {
114
nativeProps.selected = inst._wrapperState.selected;
115
}
116
87
- var content = '';
88
-
89
- // Flatten children and warn if they aren't strings or numbers;
90
- // invalid types are ignored.
91
- ReactChildren.forEach(props.children, function(child) {
92
- if (child == null) {
93
- return;
94
- }
95
- if (typeof child === 'string' || typeof child === 'number') {
96
- content += child;
97
- } else {
98
- warning(
99
- false,
100
- 'Only strings and numbers are supported as <option> children.'
101
- );
102
- }
103
- });
117
+ var content = flattenChildren(props.children);
118
119
if (content) {
120
nativeProps.children = content;
src/renderers/dom/client/wrappers/__tests__/ReactDOMOption-test.js
+25
-13
@@ -31,28 +31,18 @@ describe('ReactDOMOption', function() {
31
expect(node.innerHTML).toBe('1 foo');
32
});
33
34
- it('should ignore invalid children types', function() {
34
+ it('should ignore and warn invalid children types', function() {
35
spyOn(console, 'error');
36
var stub = <option>{1} <div /> {2}</option>;
37
stub = ReactTestUtils.renderIntoDocument(stub);
38
var node = ReactDOM.findDOMNode(stub);
39
-
39
expect(node.innerHTML).toBe('1 2');
40
+ ReactTestUtils.renderIntoDocument(<option>{1} <div /> {2}</option>);
41
+ // only warn once
42
expect(console.error.calls.length).toBe(1);
43
expect(console.error.argsForCall[0][0]).toContain('Only strings and numbers are supported as <option> children.');
44
});
45
45
- it('should warn when passing invalid children', function() {
46
- var stub = <option>{1} <div /></option>;
47
- spyOn(console, 'error');
48
- stub = ReactTestUtils.renderIntoDocument(stub);
49
-
50
- expect(console.error.calls.length).toBe(1);
51
- expect(console.error.argsForCall[0][0]).toContain(
52
- 'Only strings and numbers are supported as <option> children.'
53
- );
54
- });
55
-
46
it('should ignore null/undefined/false children without warning', function() {
47
var stub = <option>{1} {false}{true}{null}{undefined} {2}</option>;
48
spyOn(console, 'error');
@@ -82,4 +72,26 @@ describe('ReactDOMOption', function() {
72
expect(option.hasAttribute('value')).toBe(true);
73
expect(option.getAttribute('value')).toBe('lava');
74
});
75
+
76
+ it('should allow ignoring `value` on option', function() {
77
+ var a = 'a';
78
+ var stub =
79
+ <select value="giraffe" onChange={() => {}}>
80
+ <option>monkey</option>
81
+ <option>gir{a}ffe</option>
82
+ <option>gorill{a}</option>
83
+ </select>;
84
+ var options = stub.props.children;
85
+ var container = document.createElement('div');
86
+ stub = ReactDOM.render(stub, container);
87
+ var node = ReactDOM.findDOMNode(stub);
88
+
89
+ expect(node.selectedIndex).toBe(1);
90
+
91
+ ReactDOM.render(
92
+ <select value="gorilla">{options}</select>,
93
+ container
94
+ );
95
+ expect(node.selectedIndex).toEqual(2);
96
+ });
97
});