我创建了这个实时搜索组件:
class SearchEngine extends Component {
constructor (props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.handleSearch = this.handleSearch.bind(this);
}
handleChange (e) {
this.props.handleInput(e.target.value); //Redux
}
handleSearch (input, token) {
this.props.handleSearch(input, token) //Redux
};
componentWillUpdate(nextProps) {
if(this.props.input !== nextProps.input){
this.handleSearch(nextProps.input, this.props.loginToken);
}
}
render () {
let data= this.props.result;
let searchResults = data.map(item=> {
return (
<div key={item.id}>
<h3>{item.title}</h3>
<hr />
<h4>by {item.artist}</h4>
<img alt={item.id} src={item.front_picture} />
</div>
)
});
}
return (
<div>
<input name='input'
type='text'
placeholder="Search..."
value={this.props.input}
onChange={this.handleChange} />
<button onClick={() => this.handleSearch(this.props.input, this.props.loginToken)}>
Go
</button>
<div className='search_results'>
{searchResults}
</div>
</div>
)
}
它是我正在开发的 React & Redux 应用程序的一部分,并连接到 Redux 商店。问题是,当用户输入搜索查询时,它会为输入中的每个字符触发 API 调用,并创建过多的 API 调用,从而导致诸如显示先前查询结果之类的错误,而不是跟进当前查询搜索输入。
我的 api 调用(this.props.handleSearch):
export const handleSearch = (input, loginToken) => {
const API= `https://.../api/search/vector?query=${input}`;
}
return dispatch => {
fetch(API, {
headers: {
'Content-Type': 'application/json',
'Authorization': loginToken
}
}).then(res => {
if (!res.ok) {
throw Error(res.statusText);
}
return res;
}).then(res => res.json()).then(data => {
if(data.length === 0){
dispatch(handleResult('No items found.'));
}else{
dispatch(handleResult(data));
}
}).catch((error) => {
console.log(error);
});
}
};
我的意图是它会是一个实时搜索,并根据用户输入进行自我更新。但我试图找到一种方法来等待用户完成他的输入,然后应用更改以防止过多的 API 调用和错误。
建议?
编辑:
这对我有用。感谢Hammerbot 的惊人回答,我设法创建了自己的 QueueHandler 类。
export default class QueueHandler {
constructor () { // not passing any "queryFunction" parameter
this.requesting = false;
this.stack = [];
}
//instead of an "options" object I pass the api and the token for the "add" function.
//Using the options object caused errors.
add (api, token) {
if (this.stack.length < 2) {
return new Promise ((resolve, reject) => {
this.stack.push({
api,
token,
resolve,
reject
});
this.makeQuery()
})
}
return new Promise ((resolve, reject) => {
this.stack[1] = {
api,
token,
resolve,
reject
};
this.makeQuery()
})
}
makeQuery () {
if (! this.stack.length || this.requesting) {
return null
}
this.requesting = true;
// here I call fetch as a default with my api and token
fetch(this.stack[0].api, {
headers: {
'Content-Type': 'application/json',
'Authorization': this.stack[0].token
}
}).then(response => {
this.stack[0].resolve(response);
this.requesting = false;
this.stack.splice(0, 1);
this.makeQuery()
}).catch(error => {
this.stack[0].reject(error);
this.requesting = false;
this.stack.splice(0, 1);
this.makeQuery()
})
}
}
我做了一些更改以使其对我有用(请参阅评论)。
我导入它并分配了一个变量:
//searchActions.js file which contains my search related Redux actions
import QueueHandler from '../utils/QueueHandler';
let queue = new QueueHandler();
然后在我原来的 handleSearch 函数中:
export const handleSearch = (input, loginToken) => {
const API= `https://.../api/search/vector?query=${input}`;
}
return dispatch => {
queue.add(API, loginToken).then... //queue.add instead of fetch.
希望这可以帮助任何人!