React-select: Async select inputValue gets cleared on focus

Created on 16 Apr 2020  路  6Comments  路  Source: JedWatson/react-select

Description

I am trying to use the Async Select of v3.1.0. It works decently but not as I expect it to.
I can write things and search for my async options. However if I were to alt+tab out and back again, then the input will be cleared. Also if I select a value and then want to modify it, I'll have to retype everything again.

This seems like a bug, unless I have misunderstood something?

Demonstration

https://codesandbox.io/s/react-select-async-rl5gg

issubug-unconfirmed issureviewed

All 6 comments

I've noticed this behavior with regular Select as well. Focusing and blurring both clear the input value. After looking at the code it seems the default behavior is to reset the input value to an empty string in these events: onMenuClose, onInputBlur, selecting a menu value, and pressing the escape key.

Your issue is the result of onMenuClose. By default once you start typing it opens the menu, and then clicking inside the input triggers the menu to close, which clears the input value.

Also, the user's custom onMenuClose prop is called after the input is cleared, so writing your own function wouldn't help either (I think).

Here is the spot in the code if you'd like to see: Select.js#L472

Sorry I couldn't solve your issue, but maybe they'll see this and change the behavior in a future update.

I've noticed this behavior with regular Select as well. Focusing and blurring both clear the input value. After looking at the code it seems the default behavior is to reset the input value to an empty string in these events: onMenuClose, onInputBlur, selecting a menu value, and pressing the escape key.

Your issue is the result of onMenuClose. By default once you start typing it opens the menu, and then clicking inside the input triggers the menu to close, which clears the input value.

Also, the user's custom onMenuClose prop is called after the input is cleared, so writing your own function wouldn't help either (I think).

Here is the spot in the code if you'd like to see: Select.js#L472

Sorry I couldn't solve your issue, but maybe they'll see this and change the behavior in a future update.

Thank you! Your reply didn't solve it, but it shed a lot of light on the problem and I appreciate it a lot. I think I have a solution now. I thought of this solution over night, just wasn't sure of how to implement it. But with this information you gave me, it became apparent to me.

  const handleOnMenuClose = () => {
    setInputText(inputText);
  };
    <AsyncSelect
      className="auto-complete"
      value={selectedItem}
      inputValue={inputText}
      onChange={handleChange}
      onInputChange={handleOnInputChange}
      onMenuClose={onMenuClose}
      cacheOptions
      autoFocus
      noOptionsMessage={() => "No results"}
      loadOptions={getOptions}
      placeholder="Search ..."
    />

The onMenuClose solves that problem I guess. Although it don't completely work as expected still. When I tab away and then tab back, I'll have the value set, the input will be cleared although if I tab back and forth more, it'll reappear. So it feels buggy so I guess my solution isn't really great.

Seriously though, why is the input being cleared when I tab or use enter to choose value ? This doesn't make sense. So much confusing stuff going on with this Select.

Seriously though, why is the input being cleared when I tab or use enter to choose value ? This doesn't make sense. So much confusing stuff going on with this Select.

the tab/enter work for me, the "click away" that clear the inputValue is the issue (at least for me) ... :(

Update:
I take it back, the tab/enter will clear the default value... so you are right.

When isMulti is false, the input value is cleared as well when the action 'menu-close' is triggered.

Even used as a controlled component and explicitly set state when the action is 'set-value' (which is the action triggered when an option is selected from the menu) does not help.

handleInputChange = (inputValue, { action }) => {
    if (action === "set-value")  this.setState({ inputValue });
};

<AsyncSelect
    inputValue={this.state.inputValue}
    onInputChange={this.handleInputChange}
    value={this.state.value}
    onChange={this.handleChange}
    isMulti={false}
    name="colors"
    className="basic-multi-select"
    classNamePrefix="select"
/>

The strange thing is the inputValue state remains unchanged, yet the input value appeared to be cleared. I suspect this could be due to internal state change.

Here's the complete example in CodeSandbox: https://codesandbox.io/s/react-select-o6m46?file=/example.js

Greetings @SimpleCookie ,

Greetings,

The intention for better or worse is to ensure that only valid selected input is shown in the Select. The rationale is likely similar to an actual select element where the only options displayed are valid provided options. Even with Async, it could be confusing to see text that isn't fully formed as a selected option after they've left the input.

I understand that this behavior is somewhat controversial to use an input as an autocomplete, hide the input on select with an absolutely positioned label on top, and then leave the input empty making it appear as though the text is the input.

As you mentioned though, you do have control of the onBlur, onFocus, and inputValue. This means you can reset the inputValue onFocus:

const [ value, setValue ] = useState();
const [ inputValue, setInputValue ] = useState();

const onChange = option => setValue(option);
const onInputChange = (text, { action }) => (action === 'input-change') && setInputValue(text);
const onFocus = () => value && setInputValue(value.label);

<Select onFocus={onFocus} value={value} inputValue={inputValue} ... />

Another option could be to completely forgo the SingleValue and instead keep the Input always visible. In this case, I reset the input-value onBlur so it always remains.
Here is a codesandbox to see my implementation of this.

I'll be closing this issue to continue working through the backlog. If you have any further thoughts about the onBlur behavior, I have created a discussion specifically to discuss this as a possible feature request vs implementation detail here. Hope this all helps and welcome to any feedback or further discussion about this.

Was this page helpful?
0 / 5 - 0 ratings