Есть компонент, представляющий выпадающий список и поле ввода. Когда пользователь вводит текст, с сервера подтягиваются опции для выбора.
Помогите исправить такой баг: label опции, установленной в начале (через проп defaultList) отображается пустым.
import React, { Component } from 'react';
import Autocomplete from '@material-ui/lab/Autocomplete';
import TextField from '@material-ui/core/TextField';
import CheckIcon from '@material-ui/icons/Check';
/*
SearchSelect Component
Props:
- selectedIds: array of currently selected options
- onItemSelect: function, a callback function that is called when an option is selected or unselected
- label: string, the caption for the select input
- fetchList: function, a callback function that takes a query and returns a Promise that
resolves to an array of available objects from the server. The callback will only
be fired if the user has entered at least 3 characters, excluding trailing white spaces.
Returned array:
[
{ label: 'Option 1', value: 'option1' },
{ label: 'Option 2', value: 'option2' },
// ... additional options
]
- defaultList: array of the objects available without fetching from server. If fetchList is called later
and finds options with same values, their labels will be overwritten by those from server. Has the
same format as returned by fetchList.
- noOptionsMessage: string, the message to display when no options are found on the server or no proper query
Usage Example:
<SearchSelect
selectedIds={currentOptions}
onItemSelect={(selectedItems) => {
console.log('Selected items:', selectedItems);
}}
label="Caption"
fetchList={(query) => {
return fetch(https://api.example.com/search?q=${query})
.then(response => response.json())
.then(data => data.results);
}}
/>
*/
class SearchSelect extends Component {
constructor(props) {
super(props);
this.state = {
availableOptions: []
}
}
componentDidMount() {
this.setState({
availableOptions: this.props.defaultList || []
})
}
componentDidUpdate(prevProps) {
if (prevProps.defaultList !== this.props.defaultList) {
this.setState({
availableOptions: this.props.defaultList || []
});
}
}
handleFetchList = (query) => {
if (query.trim().length >= 3) {
this.props.fetchList(query).then((options) => {
const mergedOptions = options.map((option) => {
const existingOption = this.state.availableOptions.find((existing) => existing.value === option.value);
return existingOption ? { ...existingOption, label: option.label } : option;
});
this.setState({
availableOptions: [...this.props.defaultList, ...mergedOptions]
});
});
}
else {
this.setState({
availableOptions: this.props.defaultList || []
});
}
}
isOptionEqualToValue = (option, value) => {
return (option.value == value)
}
getOptionSelected = (option, value) => option.value == value;
render() {
const { selectedIds, onItemSelect, label, noOptionsMessage } = this.props;
console.log(this.props);
console.log(this.state);
return (
<Autocomplete
multiple
options={this.state.availableOptions}
getOptionLabel={ (option) => option.label }
getOptionSelected={this.getOptionSelected}
renderOption={ (option, { selected }) => (
<React.Fragment>
{ selected && <CheckIcon /> }
{ option.label }
</React.Fragment> ) }
renderInput={(params) => (
<TextField {...params} label={label} variant="outlined" />
)}
value={selectedIds}
onChange={ (event, newValue) => onItemSelect(newValue) }
onInputChange={ (event, newInputValue) => this.handleFetchList(newInputValue) }
noOptionsText={noOptionsMessage || "Ничего не найдено"}
clearText="Очистить"
openText="Открыть"
closeText="Закрыть"
style={{ marginTop: 7 }}
/>
)
}
}
SearchSelect.defaultProps = {
defaultList: [],
};
export default SearchSelect;