Skip to content

Commit

Permalink
fix(ComboBox): switch from onInputValueChange to onStateChange (#3646)
Browse files Browse the repository at this point in the history
* fix(ComboBox): switch from onInputValueChange to onStateChange

Downshift `v1`'s `onInputValueChange` seems to be called from React
state updater function and thus calling `setState()` in
`onInputValueChange` handler causes React's "An update was scheduled
from inside an update function" warning.

Fixes #2543.
Fixes #3637.

* test(ComboBox): update upon new internal API
  • Loading branch information
asudoh authored and tw15egan committed Aug 5, 2019
1 parent 9a07ade commit 141a85f
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 19 deletions.
10 changes: 7 additions & 3 deletions packages/react/src/components/ComboBox/ComboBox-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const downshiftActions = {
setHighlightedIndex: jest.fn(),
};
const clearInput = wrapper =>
wrapper.instance().handleOnInputValueChange('', downshiftActions);
wrapper.instance().handleOnStateChange({ inputValue: '' }, downshiftActions);

describe('ComboBox', () => {
let mockProps;
Expand Down Expand Up @@ -156,10 +156,14 @@ describe('ComboBox', () => {
it('should set `inputValue` to an empty string if a falsey-y value is given', () => {
const wrapper = mount(<ComboBox {...mockProps} />);

wrapper.instance().handleOnInputValueChange('foo', downshiftActions);
wrapper
.instance()
.handleOnStateChange({ inputValue: 'foo' }, downshiftActions);
expect(wrapper.state('inputValue')).toBe('foo');

wrapper.instance().handleOnInputValueChange(null, downshiftActions);
wrapper
.instance()
.handleOnStateChange({ inputValue: null }, downshiftActions);
expect(wrapper.state('inputValue')).toBe('');
});
});
Expand Down
35 changes: 19 additions & 16 deletions packages/react/src/components/ComboBox/ComboBox.js
Original file line number Diff line number Diff line change
Expand Up @@ -204,22 +204,25 @@ export default class ComboBox extends React.Component {
event.stopPropagation();
};

handleOnInputValueChange = (inputValue, { setHighlightedIndex }) => {
const { onInputChange } = this.props;

setHighlightedIndex(findHighlightedIndex(this.props, inputValue));

this.setState(
() => ({
// Default to empty string if we have a false-y `inputValue`
inputValue: inputValue || '',
}),
() => {
if (onInputChange) {
onInputChange(inputValue);
handleOnStateChange = (newState, { setHighlightedIndex }) => {
if (Object.prototype.hasOwnProperty.call(newState, 'inputValue')) {
const { inputValue } = newState;
const { onInputChange } = this.props;

setHighlightedIndex(findHighlightedIndex(this.props, inputValue));

this.setState(
() => ({
// Default to empty string if we have a false-y `inputValue`
inputValue: inputValue || '',
}),
() => {
if (onInputChange) {
onInputChange(inputValue);
}
}
}
);
);
}
};

onToggleClick = isOpen => event => {
Expand Down Expand Up @@ -276,7 +279,7 @@ export default class ComboBox extends React.Component {
<Downshift
{...downshiftProps}
onChange={this.handleOnChange}
onInputValueChange={this.handleOnInputValueChange}
onStateChange={this.handleOnStateChange}
inputValue={this.state.inputValue || ''}
itemToString={itemToString}
defaultSelectedItem={initialSelectedItem}>
Expand Down

0 comments on commit 141a85f

Please sign in to comment.