Я создал fuzzy search
компонент реакции.Намерение состоит в том, чтобы иметь возможность ввести имя набора данных в input
, и datalist
заполняется предложениями о близком соответствии с текущим значением.Базовый дизайн был реализован и отлично работает.
CodeSandbox: https://codesandbox.io/s/38yxk6wqq1
У меня возникли две проблемы:
1) Datalist не распознаетwhitespace
.Если строки поиска разделены whitespace
, datalist
не заполняется.Чтобы учесть это, я заменяю символы whitespace
на _
. Идентификатор * не обязательно заменяет символы , так как результаты fuse.js
действительны и точны.Это тег datalist
, который не похож на то, что я делаю.
2) Datalist
не заполняется при редактировании середины строки.Допустим, пользователь вводит строку поиска, например, freki_talis_lagg_test_05
, datalist
соответствующим образом ищет и заполняет правильно.Если пользователь затем редактирует входную строку в freki_talis__test_05
, а затем снова редактирует ее из середины строки в freki_talis_lagg_test_05
, datalist
не рендерится, даже если fuse.js
вернул соответствующие результаты и мой асинхронный вызовк моей базе данных работает.
Это немного сложно сформулировать в тексте, поэтому я создал короткий gif ниже:
import React from 'react';
import Fuse from 'fuse.js';
import _ from 'lodash';
class DatasetSearch extends React.Component {
constructor(props) {
super(props);
this.state = {
datasets: [{"name":"freki_recorder_test_20180404_093731"},{"name":"freki_talis_lagg_test_05"},{"name":"freki_talis_lagg_test_03"},{"name":"freki_talis_lagg_test_02"},{"name":"freki_recorder_test_20180403_irb_force_2"}],
name: this.props.datasetName,
results: [],
options: {
shouldSort: true,
threshold: 0.6,
location: 0,
distance: 100,
maxPatternLength: 32,
minMatchCharLength: 1,
keys: [
"name",
]
},
};
this.handleChange = this.handleChange.bind(this);
this.handleFuzzySearch = this.handleFuzzySearch.bind(this);
}
handleChange(e) {
const { handleUpdateConfig } = this.props;
const value = _.replace(e.target.value, ' ', '_');
console.log(value);
this.setState({
name: value
}, () => {
this.handleFuzzySearch(this.state.name);
})
}
handleFuzzySearch(value) {
const { datasets } = this.props;
const { options } = this.state;
const fuse = new Fuse(this.state.datasets, options);
const results = fuse.search(value).slice(0,5);
this.setState({
results: results
});
}
render() {
const { results } = this.state;
return (
<div style={{width: '100%'}}>
<input type='search' list='datasets' onChange={this.handleChange} style={{width: '100%'}} value={this.state.name}/>
<datalist id='datasets'>
{ results.map((dataset) => <option key={dataset.id} value={dataset.name} />) }
</datalist>
</div>
);
}
}