最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Is there any way to prevent react-select (Select.Async) from deleting the search input value on unfocus? - Stack Ov

programmeradmin4浏览0评论

Situation:
I have one normal select(categories), which determines what Options are loaded for the Select.Async from react-select.

Problem:
Lets say someone searches for an option in Select.Async, while category A is selected. Then he realizes, that the option he is searching for is only available in category B. So he switches category in the first select. But while he clicks out of the search box from Select.Async, the input he made vanishes and he has to type it again.

Is there something I can do to keep his input even if I update the set of options while the search input is not in focus?

<select id="categories">
    <option value="1" selected>A</option>
    <option value="2">B</option>
    <option value="3">C</option>
</select>

<Select.Async loadOptions={load} />

Complete code-sample

Situation:
I have one normal select(categories), which determines what Options are loaded for the Select.Async from react-select.

Problem:
Lets say someone searches for an option in Select.Async, while category A is selected. Then he realizes, that the option he is searching for is only available in category B. So he switches category in the first select. But while he clicks out of the search box from Select.Async, the input he made vanishes and he has to type it again.

Is there something I can do to keep his input even if I update the set of options while the search input is not in focus?

<select id="categories">
    <option value="1" selected>A</option>
    <option value="2">B</option>
    <option value="3">C</option>
</select>

<Select.Async loadOptions={load} />

Complete code-sample

Share Improve this question asked Aug 10, 2017 at 13:28 S.BabovicS.Babovic 3356 silver badges17 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 6

I found it out:

the property value of Select.Async is not the actual value of the input field. If you want to set the value of the input, there is a prop called inputRenderer. There you define an input within a div with all predefined inputProps (simply write <input {...inputProps}) and handle the value on your own.

render(){
    var inputChange = (input) => this.setState({value: input});
    var renderInput = (inputProps) => {
        if(this.state.value == ''){
            this.state.placeholder = 'Select ...';
        } else {
            this.state.placeholder = '';
        }
        var setCurserPosAtEnd = (event) => {
            if(event.target)
                event.target.setSelectionRange(event.target.value.length, event.target.value.length);
        }
        return (
            <div className='Select-input'>
                <input {...inputProps} value={this.state.value} onFocus={setCurserPosAtEnd} />
            </div>
        );
    }
    return(
        ...
        <Select.Async 
            loadOptions={loadOptionHandler} 
            onBlurResetsInput={false} 
            onCloseResetsInput={false} 
            inputRenderer={renderInput} 
            placeholder={this.state.placeholder} 
            onInputChange={inputChange} />
        ...
    );
}

I think this is the prop you are looking after:

<Select.Async loadOptions={load} onBlurResetsInput={false}/>

More options here

The full working example:

export default class Layout extends React.Component {

  constructor()
  {
     super();
     this.state = {value: ""};  
  }

  render(){
    var load = (input, callback) => this.load(input, callback);
    return (
      <div class="container">
        <select id="select">
          <option value="1" selected>A</option>
          <option value="2">B</option>
          <option value="3">C</option>
        </select>

        <Select.Async 
          value={this.state.value}
          onBlurResetsInput={false}
          onChange={(newValue) => {
            this.setState({value: newValue});
          }}           
          loadOptions={load} />
      </div>
    );
  }

  load(input, callback){
    var select = document.getElementById("select");
    var selected = select.options[select.selectedIndex].value;
    console.log(selected);
    var options = [];
    switch(selected){
      case "1":
        options = [{label: "A", value: 1}, {label: "B", value: 2}, {label: "C", value: 3}];
        break;
      case "2":
        options = [{label: "D", value: 4}, {label: "E", value: 5}, {label: "F", value: 6}];
        break;
      case "3":
        options = [{label: "G", value: 7}, {label: "H", value: 8}, {label: "I", value: 9}];
        break;
    }

    callback(null, {
      options: options
    });
  }
}

One way to do that is to use inputValue prop.

Basically we modify the related state variable inside onInputChangeHandler and onMenuCloseHandler event handlers.

E.x.

const Bar = React.memo((props: PropsWithChildren<any>) => {
    const searchRef = useRef<any>();

    const [inputValue, setInputValue] = useState<any>('');

    useEffect(() => {
        setTimeout(() => {
            searchRef.current.focus();
        });
    });

    useEffect(() => {
        if (props.lastSelectedOption)
            setInputValue(props.lastSelectedOption.value);
    }, [props.lastSelectedOption]);

    const onSearchChangeHandler = async (event) => {
        //...
    });

    const onInputChangeHandler = (inputValue, { action }) => {
        setInputValue(inputValue);

        if (action == 'input-change' && !inputValue) props.setLastSelectedOption(null);
    }

    const onKeyDownHandler = () => {
        setTimeout(() => {
            searchRef.current.focus();
        });
    };

    const onMenuCloseHandler = () => setInputValue(inputValue);

    return (
        <div className="d-inline-flex w-100">
            <AsyncSelect
                className="rounded-pill flex-grow-1"
                placeholder="Search.."
                ref={searchRef}
                inputValue={inputValue}
                value={props.lastSelectedOption}
                onChange={onChangeHandler}
                onInputChange={onInputChangeHandler}
                onKeyDown={onKeyDownHandler}
                onMenuClose={onMenuCloseHandler}
            />
        </div>
    )
})

In the code above, prop lastSelectedOption is an object like this

{
    value: event.value,
    label: event.label
}
发布评论

评论列表(0)

  1. 暂无评论