Skip to content

Commit cb4b948

Browse files
authored
Merge pull request #4339 from Methuselah96/on-change-null
Modify onChange with empty value behaviour for multi select to always pass an empty array
2 parents 45f6f29 + 07a3997 commit cb4b948

File tree

3 files changed

+65
-48
lines changed

3 files changed

+65
-48
lines changed

.changeset/dry-pumas-complain.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"react-select": major
3+
---
4+
5+
Standardized value passed to onChange

packages/react-select/src/Select.js

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -702,12 +702,18 @@ export default class Select extends Component<Props, State> {
702702
}
703703
};
704704
removeValue = (removedValue: OptionType) => {
705+
const { isMulti } = this.props;
705706
const { selectValue } = this.state;
706707
const candidate = this.getOptionValue(removedValue);
707-
const newValue = selectValue.filter(
708+
const newValueArray = selectValue.filter(
708709
i => this.getOptionValue(i) !== candidate
709710
);
710-
this.onChange(newValue.length ? newValue : null, {
711+
const newValue = isMulti
712+
? newValueArray
713+
: newValueArray.length > 0
714+
? newValueArray[0]
715+
: null;
716+
this.onChange(newValue, {
711717
action: 'remove-value',
712718
removedValue,
713719
});
@@ -720,19 +726,25 @@ export default class Select extends Component<Props, State> {
720726
this.focusInput();
721727
};
722728
clearValue = () => {
723-
this.onChange(null, { action: 'clear' });
729+
this.onChange(this.props.isMulti ? [] : null, { action: 'clear' });
724730
};
725731
popValue = () => {
732+
const { isMulti } = this.props;
726733
const { selectValue } = this.state;
727734
const lastSelectedValue = selectValue[selectValue.length - 1];
728-
const newValue = selectValue.slice(0, selectValue.length - 1);
735+
const newValueArray = selectValue.slice(0, selectValue.length - 1);
736+
const newValue = isMulti
737+
? newValueArray
738+
: newValueArray.length > 0
739+
? newValueArray[0]
740+
: null;
729741
this.announceAriaLiveSelection({
730742
event: 'pop-value',
731743
context: {
732744
value: lastSelectedValue ? this.getOptionLabel(lastSelectedValue) : '',
733745
},
734746
});
735-
this.onChange(newValue.length ? newValue : null, {
747+
this.onChange(newValue, {
736748
action: 'pop-value',
737749
removedValue: lastSelectedValue,
738750
});

packages/react-select/src/__tests__/Select.test.js

Lines changed: 43 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1643,48 +1643,48 @@ test('should not call onChange on hitting backspace even when backspaceRemovesVa
16431643
expect(onChangeSpy).not.toHaveBeenCalled();
16441644
});
16451645

1646-
cases(
1647-
'should call onChange with `null` on hitting backspace when backspaceRemovesValue is true',
1648-
({ props = { ...BASIC_PROPS }, expectedValue }) => {
1649-
let onChangeSpy = jest.fn();
1650-
let { container } = render(
1651-
<Select
1652-
{...props}
1653-
backspaceRemovesValue
1654-
isClearable
1655-
onChange={onChangeSpy}
1656-
/>
1657-
);
1658-
fireEvent.keyDown(container.querySelector('.react-select__control'), {
1659-
keyCode: 8,
1660-
key: 'Backspace',
1661-
});
1662-
expect(onChangeSpy).toHaveBeenCalledWith(null, expectedValue);
1663-
},
1664-
{
1665-
'and isMulti is false': {
1666-
props: {
1667-
...BASIC_PROPS,
1668-
isMulti: false,
1669-
},
1670-
expectedValue: {
1671-
action: 'clear',
1672-
name: 'test-input-name',
1673-
},
1674-
},
1675-
'and isMulti is true': {
1676-
props: {
1677-
...BASIC_PROPS,
1678-
isMulti: true,
1679-
},
1680-
expectedValue: {
1681-
action: 'pop-value',
1682-
name: 'test-input-name',
1683-
removedValue: undefined,
1684-
},
1685-
},
1686-
}
1687-
);
1646+
test('should call onChange with `null` on hitting backspace when backspaceRemovesValue is true and isMulti is false', () => {
1647+
let onChangeSpy = jest.fn();
1648+
let { container } = render(
1649+
<Select
1650+
{...BASIC_PROPS}
1651+
backspaceRemovesValue
1652+
isClearable
1653+
isMulti={false}
1654+
onChange={onChangeSpy}
1655+
/>
1656+
);
1657+
fireEvent.keyDown(container.querySelector('.react-select__control'), {
1658+
keyCode: 8,
1659+
key: 'Backspace',
1660+
});
1661+
expect(onChangeSpy).toHaveBeenCalledWith(null, {
1662+
action: 'clear',
1663+
name: 'test-input-name',
1664+
});
1665+
});
1666+
1667+
test('should call onChange with an array on hitting backspace when backspaceRemovesValue is true and isMulti is true', () => {
1668+
let onChangeSpy = jest.fn();
1669+
let { container } = render(
1670+
<Select
1671+
{...BASIC_PROPS}
1672+
backspaceRemovesValue
1673+
isClearable
1674+
isMulti
1675+
onChange={onChangeSpy}
1676+
/>
1677+
);
1678+
fireEvent.keyDown(container.querySelector('.react-select__control'), {
1679+
keyCode: 8,
1680+
key: 'Backspace',
1681+
});
1682+
expect(onChangeSpy).toHaveBeenCalledWith([], {
1683+
action: 'pop-value',
1684+
name: 'test-input-name',
1685+
removedValue: undefined,
1686+
});
1687+
});
16881688

16891689
test('multi select > clicking on X next to option will call onChange with all options other that the clicked option', () => {
16901690
let onChangeSpy = jest.fn();
@@ -2305,7 +2305,7 @@ test('clear select by clicking on clear button > should not call onMenuOpen', ()
23052305
container.querySelector('.react-select__clear-indicator'),
23062306
{ button: 0 }
23072307
);
2308-
expect(onChangeSpy).toBeCalledWith(null, {
2308+
expect(onChangeSpy).toBeCalledWith([], {
23092309
action: 'clear',
23102310
name: BASIC_PROPS.name,
23112311
});

0 commit comments

Comments
 (0)