Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add prevInputValue to action meta #4785

Merged
merged 10 commits into from Oct 28, 2021
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/gorgeous-berries-tan.md
@@ -0,0 +1,5 @@
---
'react-select': minor
---

Add current `inputValue` to action meta
Rall3n marked this conversation as resolved.
Show resolved Hide resolved
24 changes: 11 additions & 13 deletions docs/examples/OnSelectResetsInput.tsx
Expand Up @@ -3,43 +3,41 @@ import Select, { InputActionMeta } from 'react-select';
import { colourOptions } from '../data';

interface State {
readonly inputValue: string;
readonly menuIsOpen?: boolean;
}

export default class OnSelectResetsInput extends Component<{}, State> {
state: State = {
inputValue: '',
};
onInputChange = (inputValue: string, { action }: InputActionMeta) => {
state: State = {};
onInputChange = (
inputValue: string,
{ action, prevInputValue }: InputActionMeta
) => {
console.log(inputValue, action);
switch (action) {
case 'input-change':
this.setState({ inputValue });
return;
return inputValue;
case 'menu-close':
console.log(this.state.inputValue);
console.log(prevInputValue);
let menuIsOpen = undefined;
if (this.state.inputValue) {
if (prevInputValue) {
menuIsOpen = true;
}
this.setState({
menuIsOpen,
});
return;
return prevInputValue;
default:
return;
return prevInputValue;
}
};
render() {
const { inputValue, menuIsOpen } = this.state;
const { menuIsOpen } = this.state;
return (
<Select
isMulti
defaultValue={colourOptions[0]}
isClearable
isSearchable
inputValue={inputValue}
onInputChange={this.onInputChange}
name="color"
options={colourOptions}
Expand Down
20 changes: 14 additions & 6 deletions packages/react-select/src/Select.tsx
Expand Up @@ -758,7 +758,10 @@ export default class Select<
this.props.onMenuOpen();
}
onMenuClose() {
this.onInputChange('', { action: 'menu-close' });
this.onInputChange('', {
action: 'menu-close',
prevInputValue: this.props.inputValue,
});
this.props.onMenuClose();
}
onInputChange(newValue: string, actionMeta: InputActionMeta) {
Expand Down Expand Up @@ -896,8 +899,8 @@ export default class Select<
action: SetValueAction,
option?: Option
) => {
const { closeMenuOnSelect, isMulti } = this.props;
this.onInputChange('', { action: 'set-value' });
const { closeMenuOnSelect, isMulti, inputValue } = this.props;
this.onInputChange('', { action: 'set-value', prevInputValue: inputValue });
if (closeMenuOnSelect) {
this.setState({ inputIsHiddenAfterUpdate: !isMulti });
this.onMenuClose();
Expand Down Expand Up @@ -1345,9 +1348,10 @@ export default class Select<
// ==============================

handleInputChange: FormEventHandler<HTMLInputElement> = (event) => {
const { inputValue: prevInputValue } = this.props;
const inputValue = event.currentTarget.value;
this.setState({ inputIsHiddenAfterUpdate: false });
this.onInputChange(inputValue, { action: 'input-change' });
this.onInputChange(inputValue, { action: 'input-change', prevInputValue });
if (!this.props.menuIsOpen) {
this.onMenuOpen();
}
Expand All @@ -1366,14 +1370,15 @@ export default class Select<
this.openAfterFocus = false;
};
onInputBlur: FocusEventHandler<HTMLInputElement> = (event) => {
const { inputValue: prevInputValue } = this.props;
if (this.menuListRef && this.menuListRef.contains(document.activeElement)) {
this.inputRef!.focus();
return;
}
if (this.props.onBlur) {
this.props.onBlur(event);
}
this.onInputChange('', { action: 'input-blur' });
this.onInputChange('', { action: 'input-blur', prevInputValue });
this.onMenuClose();
this.setState({
focusedValue: null,
Expand Down Expand Up @@ -1475,7 +1480,10 @@ export default class Select<
case 'Escape':
if (menuIsOpen) {
this.setState({ inputIsHiddenAfterUpdate: false });
this.onInputChange('', { action: 'menu-close' });
this.onInputChange('', {
action: 'menu-close',
prevInputValue: inputValue,
});
this.onMenuClose();
} else if (isClearable && escapeClearsValue) {
this.clearValue();
Expand Down
11 changes: 9 additions & 2 deletions packages/react-select/src/__tests__/Select.test.tsx
Expand Up @@ -1290,7 +1290,10 @@ cases(
keyCode: 27,
key: 'Escape',
});
expect(spy).toHaveBeenCalledWith('', { action: 'menu-close' });
expect(spy).toHaveBeenCalledWith('', {
action: 'menu-close',
prevInputValue: 'test',
});
},
{
'single select > should call onInputChange prop with empty string as inputValue':
Expand Down Expand Up @@ -3013,9 +3016,13 @@ test('close menu on hitting escape and clear input value if menu is open even if
expect(onMenuCloseSpy).toHaveBeenCalled();
// once by onMenuClose and other is direct
expect(onInputChangeSpy).toHaveBeenCalledTimes(2);
expect(onInputChangeSpy).toHaveBeenCalledWith('', { action: 'menu-close' });
expect(onInputChangeSpy).toHaveBeenCalledWith('', {
action: 'menu-close',
prevInputValue: '',
});
expect(onInputChangeSpy).toHaveBeenLastCalledWith('', {
action: 'menu-close',
prevInputValue: '',
});
});

Expand Down
2 changes: 2 additions & 0 deletions packages/react-select/src/types.ts
Expand Up @@ -171,6 +171,8 @@ export type InputAction =

export interface InputActionMeta {
action: InputAction;
/** The previous value of the search input. */
prevInputValue: string;
}

export type MenuPlacement = 'auto' | 'bottom' | 'top';
Expand Down