React Async Select loadoption sometimes fail to loads the option. This is a very strange phenomenon after couple of set of queries react loadoptions don't load any value but i can see from log that results properly came from backend query. My codebase is totally up to date with react-select new release and using
"react-select": "^2.1.1"
Here is my front end code for react-async select component. I do use debounce in my getOptions function to reduce number of backend search query. This should not cause any problem i guess. I would like to add another point that i observe in this case, loadoptions serach indicator ( ... ) also not appear in this phenomenon.
import React from 'react';
import AsyncSelect from 'react-select/lib/Async';
import Typography from '@material-ui/core/Typography';
import i18n from 'react-intl-universal';
const _ = require('lodash');
class SearchableSelect extends React.Component {
constructor(props) {
super(props);
this.state = {
inputValue: '',
searchApiUrl: props.searchApiUrl,
limit: props.limit,
selectedOption: this.props.defaultValue
};
this.getOptions = _.debounce(this.getOptions.bind(this), 500);
//this.getOptions = this.getOptions.bind(this);
this.handleChange = this.handleChange.bind(this);
this.noOptionsMessage = this.noOptionsMessage.bind(this);
this.handleInputChange = this.handleInputChange.bind(this);
}
handleChange(selectedOption) {
this.setState({
selectedOption: selectedOption
});
if (this.props.actionOnSelectedOption) {
// this is for update action on selectedOption
this.props.actionOnSelectedOption(selectedOption.value);
}
}
handleInputChange(inputValue) {
this.setState({ inputValue });
return inputValue;
}
async getOptions(inputValue, callback) {
console.log('in getOptions'); // never print
if (!inputValue) {
return callback([]);
}
const response = await fetch(
`${this.state.searchApiUrl}?search=${inputValue}&limit=${
this.state.limit
}`
);
const json = await response.json();
console.log('results', json.results); // never print
return callback(json.results);
}
noOptionsMessage(props) {
if (this.state.inputValue === '') {
return (
<Typography {...props.innerProps} align="center" variant="title">
{i18n.get('app.commons.label.search')}
</Typography>
);
}
return (
<Typography {...props.innerProps} align="center" variant="title">
{i18n.get('app.commons.errors.emptySearchResult')}
</Typography>
);
}
getOptionValue = option => {
return option.value || option.id;
};
getOptionLabel = option => {
return option.label || option.name;
};
render() {
const { defaultOptions, placeholder } = this.props;
return (
<AsyncSelect
cacheOptions
value={this.state.selectedOption}
noOptionsMessage={this.noOptionsMessage}
getOptionValue={this.getOptionValue}
getOptionLabel={this.getOptionLabel}
defaultOptions={defaultOptions}
loadOptions={this.getOptions}
placeholder={placeholder}
onChange={this.handleChange}
/>
);
}
}
export default SearchableSelect;
Edit to response Steve's answer
Thank you for your answer Steve. Still no luck. I try to response according to your response points.
- If i don't use optionsValue, rather use getOptionValue and getOptionLevel then query result don't loaded properly. I mean there blank options loaded, no text value.
- yes you are right, is a synchronous method returning a string, i don't need to override this. And this working fine and noOptionsMessage shows properly. Thanks to point this out.
- actionOnSelectedOption is not a noop method, its may have some responsibility to perform. I try to use SearchableSelect as an independent component, if i need some back-end action to do this function will trigger that accordingly. For example, i use this in my project's user-profile, where user can update his school/college information from existing entries. When user select an option there is a profile update responsibility to perform.
- Yes you are right. I don't need to maintain inputValue in state, thanks.
- I do make sure defaultOptions is an array.
- I do test without using debounce, still no luck. i am using debounce to limit the backend call, otherwise there may a backend call for every key-stroke that surely i don't want.
async select work perfectly for 2/3 queries and after that it suddenly stop working. One distinguishable behaviour i observe that for those cases search indicators ( ... ) also not showing.
Thank you so much for you time.
Edit 2 to response Steve's answer
Thank you so much for your response again. I was wrong about getOptionValue and getOptionLabel. If loadOptions got response both these function called. So i removed my helper optionsValue function from my previous code snippet and update my code-snippet according to ( In this post also ). But still no luck. In some cases async-select didn't work. I try to take a screenshot one such case. I do name use in my local-db name "tamim johnson" but when i search him i didn't get any response but got proper response back from back-end. Here is the screenshot of this case
I not sure how clear this screenshot is. Tamim johnson also in 6th position in my ranklist.
Thank you sir for your time. I have no clue what i am doing wrong or missing something.
Edit 3 to response Steve's answer
This is preview tab response for user search named "tamim johnson".