Ignore symbols and functions in select tag (#13389)
* wip: ignore symbols and functions in select tag * fix: Use ToStringValue as a maybe type * refactor: remove unnecessary test * refactor: remove implicit return from tests
This commit is contained in:
parent
e3d5b5ea7f
commit
de5102c4cd
|
@ -808,4 +808,176 @@ describe('ReactDOMSelect', () => {
|
||||||
expect(node.options[1].selected).toBe(false); // b
|
expect(node.options[1].selected).toBe(false); // b
|
||||||
expect(node.options[2].selected).toBe(false); // c
|
expect(node.options[2].selected).toBe(false); // c
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('When given a Symbol value', () => {
|
||||||
|
it('treats initial Symbol value as an empty string', () => {
|
||||||
|
let node;
|
||||||
|
|
||||||
|
expect(() => {
|
||||||
|
node = ReactTestUtils.renderIntoDocument(
|
||||||
|
<select onChange={noop} value={Symbol('foobar')}>
|
||||||
|
<option value={Symbol('foobar')}>A Symbol!</option>
|
||||||
|
<option value="monkey">A monkey!</option>
|
||||||
|
<option value="giraffe">A giraffe!</option>
|
||||||
|
</select>,
|
||||||
|
);
|
||||||
|
}).toWarnDev('Invalid value for prop `value`');
|
||||||
|
|
||||||
|
expect(node.value).toBe('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('treats updated Symbol value as an empty string', () => {
|
||||||
|
let node;
|
||||||
|
|
||||||
|
expect(() => {
|
||||||
|
node = ReactTestUtils.renderIntoDocument(
|
||||||
|
<select onChange={noop} value="monkey">
|
||||||
|
<option value={Symbol('foobar')}>A Symbol!</option>
|
||||||
|
<option value="monkey">A monkey!</option>
|
||||||
|
<option value="giraffe">A giraffe!</option>
|
||||||
|
</select>,
|
||||||
|
);
|
||||||
|
}).toWarnDev('Invalid value for prop `value`');
|
||||||
|
|
||||||
|
expect(node.value).toBe('monkey');
|
||||||
|
|
||||||
|
node = ReactTestUtils.renderIntoDocument(
|
||||||
|
<select onChange={noop} value={Symbol('foobar')}>
|
||||||
|
<option value={Symbol('foobar')}>A Symbol!</option>
|
||||||
|
<option value="monkey">A monkey!</option>
|
||||||
|
<option value="giraffe">A giraffe!</option>
|
||||||
|
</select>,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(node.value).toBe('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('treats initial Symbol defaultValue as an empty string', () => {
|
||||||
|
let node;
|
||||||
|
|
||||||
|
expect(() => {
|
||||||
|
node = ReactTestUtils.renderIntoDocument(
|
||||||
|
<select defaultValue={Symbol('foobar')}>
|
||||||
|
<option value={Symbol('foobar')}>A Symbol!</option>
|
||||||
|
<option value="monkey">A monkey!</option>
|
||||||
|
<option value="giraffe">A giraffe!</option>
|
||||||
|
</select>,
|
||||||
|
);
|
||||||
|
}).toWarnDev('Invalid value for prop `value`');
|
||||||
|
|
||||||
|
expect(node.value).toBe('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('treats updated Symbol defaultValue as an empty string', () => {
|
||||||
|
let node;
|
||||||
|
|
||||||
|
expect(() => {
|
||||||
|
node = ReactTestUtils.renderIntoDocument(
|
||||||
|
<select defaultValue="monkey">
|
||||||
|
<option value={Symbol('foobar')}>A Symbol!</option>
|
||||||
|
<option value="monkey">A monkey!</option>
|
||||||
|
<option value="giraffe">A giraffe!</option>
|
||||||
|
</select>,
|
||||||
|
);
|
||||||
|
}).toWarnDev('Invalid value for prop `value`');
|
||||||
|
|
||||||
|
expect(node.value).toBe('monkey');
|
||||||
|
|
||||||
|
node = ReactTestUtils.renderIntoDocument(
|
||||||
|
<select defaultValue={Symbol('foobar')}>
|
||||||
|
<option value={Symbol('foobar')}>A Symbol!</option>
|
||||||
|
<option value="monkey">A monkey!</option>
|
||||||
|
<option value="giraffe">A giraffe!</option>
|
||||||
|
</select>,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(node.value).toBe('');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('When given a function value', () => {
|
||||||
|
it('treats initial function value as an empty string', () => {
|
||||||
|
let node;
|
||||||
|
|
||||||
|
expect(() => {
|
||||||
|
node = ReactTestUtils.renderIntoDocument(
|
||||||
|
<select onChange={noop} value={() => {}}>
|
||||||
|
<option value={() => {}}>A function!</option>
|
||||||
|
<option value="monkey">A monkey!</option>
|
||||||
|
<option value="giraffe">A giraffe!</option>
|
||||||
|
</select>,
|
||||||
|
);
|
||||||
|
}).toWarnDev('Invalid value for prop `value`');
|
||||||
|
|
||||||
|
expect(node.value).toBe('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('treats initial function defaultValue as an empty string', () => {
|
||||||
|
let node;
|
||||||
|
|
||||||
|
expect(() => {
|
||||||
|
node = ReactTestUtils.renderIntoDocument(
|
||||||
|
<select defaultValue={() => {}}>
|
||||||
|
<option value={() => {}}>A function!</option>
|
||||||
|
<option value="monkey">A monkey!</option>
|
||||||
|
<option value="giraffe">A giraffe!</option>
|
||||||
|
</select>,
|
||||||
|
);
|
||||||
|
}).toWarnDev('Invalid value for prop `value`');
|
||||||
|
|
||||||
|
expect(node.value).toBe('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('treats updated function value as an empty string', () => {
|
||||||
|
let node;
|
||||||
|
|
||||||
|
expect(() => {
|
||||||
|
node = ReactTestUtils.renderIntoDocument(
|
||||||
|
<select onChange={noop} value="monkey">
|
||||||
|
<option value={() => {}}>A function!</option>
|
||||||
|
<option value="monkey">A monkey!</option>
|
||||||
|
<option value="giraffe">A giraffe!</option>
|
||||||
|
</select>,
|
||||||
|
);
|
||||||
|
}).toWarnDev('Invalid value for prop `value`');
|
||||||
|
|
||||||
|
expect(node.value).toBe('monkey');
|
||||||
|
|
||||||
|
node = ReactTestUtils.renderIntoDocument(
|
||||||
|
<select onChange={noop} value={() => {}}>
|
||||||
|
<option value={() => {}}>A function!</option>
|
||||||
|
<option value="monkey">A monkey!</option>
|
||||||
|
<option value="giraffe">A giraffe!</option>
|
||||||
|
</select>,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(node.value).toBe('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('treats updated function defaultValue as an empty string', () => {
|
||||||
|
let node;
|
||||||
|
|
||||||
|
expect(() => {
|
||||||
|
node = ReactTestUtils.renderIntoDocument(
|
||||||
|
<select defaultValue="monkey">
|
||||||
|
<option value={() => {}}>A function!</option>
|
||||||
|
<option value="monkey">A monkey!</option>
|
||||||
|
<option value="giraffe">A giraffe!</option>
|
||||||
|
</select>,
|
||||||
|
);
|
||||||
|
}).toWarnDev('Invalid value for prop `value`');
|
||||||
|
|
||||||
|
expect(node.value).toBe('monkey');
|
||||||
|
|
||||||
|
node = ReactTestUtils.renderIntoDocument(
|
||||||
|
<select defaultValue={() => {}}>
|
||||||
|
<option value={() => {}}>A function!</option>
|
||||||
|
<option value="monkey">A monkey!</option>
|
||||||
|
<option value="giraffe">A giraffe!</option>
|
||||||
|
</select>,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(node.value).toBe('');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import warning from 'shared/warning';
|
import warning from 'shared/warning';
|
||||||
import {validateDOMNesting, updatedAncestorInfo} from './validateDOMNesting';
|
import {validateDOMNesting, updatedAncestorInfo} from './validateDOMNesting';
|
||||||
|
import {getToStringValue, toString} from './ToStringValue';
|
||||||
|
|
||||||
let didWarnSelectedSetOnOption = false;
|
let didWarnSelectedSetOnOption = false;
|
||||||
|
|
||||||
|
@ -73,7 +74,7 @@ export function validateProps(element: Element, props: Object) {
|
||||||
export function postMountWrapper(element: Element, props: Object) {
|
export function postMountWrapper(element: Element, props: Object) {
|
||||||
// value="" should make a value attribute (#6219)
|
// value="" should make a value attribute (#6219)
|
||||||
if (props.value != null) {
|
if (props.value != null) {
|
||||||
element.setAttribute('value', props.value);
|
element.setAttribute('value', toString(getToStringValue(props.value)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,8 @@ import {getCurrentFiberOwnerNameInDevOrNull} from 'react-reconciler/src/ReactCur
|
||||||
import warning from 'shared/warning';
|
import warning from 'shared/warning';
|
||||||
|
|
||||||
import ReactControlledValuePropTypes from '../shared/ReactControlledValuePropTypes';
|
import ReactControlledValuePropTypes from '../shared/ReactControlledValuePropTypes';
|
||||||
|
import {getToStringValue, toString} from './ToStringValue';
|
||||||
|
import type {ToStringValue} from './ToStringValue';
|
||||||
|
|
||||||
let didWarnValueDefaultValue;
|
let didWarnValueDefaultValue;
|
||||||
|
|
||||||
|
@ -21,7 +23,7 @@ if (__DEV__) {
|
||||||
|
|
||||||
type SelectWithWrapperState = HTMLSelectElement & {
|
type SelectWithWrapperState = HTMLSelectElement & {
|
||||||
_wrapperState: {
|
_wrapperState: {
|
||||||
initialValue: ?string,
|
initialValue: ?ToStringValue,
|
||||||
wasMultiple: boolean,
|
wasMultiple: boolean,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -98,7 +100,7 @@ function updateOptions(
|
||||||
} else {
|
} else {
|
||||||
// Do not set `select.value` as exact behavior isn't consistent across all
|
// Do not set `select.value` as exact behavior isn't consistent across all
|
||||||
// browsers for all cases.
|
// browsers for all cases.
|
||||||
let selectedValue = '' + (propValue: string);
|
let selectedValue = toString(getToStringValue((propValue: any)));
|
||||||
let defaultSelected = null;
|
let defaultSelected = null;
|
||||||
for (let i = 0; i < options.length; i++) {
|
for (let i = 0; i < options.length; i++) {
|
||||||
if (options[i].value === selectedValue) {
|
if (options[i].value === selectedValue) {
|
||||||
|
|
Loading…
Reference in New Issue