如何在用户停止输入时才开始搜索?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在用户停止输入时才开始搜索?相关的知识,希望对你有一定的参考价值。
我需要在用户停止输入时进行搜索.我知道我应该使用的是 setTimeout() . 但随着 Reactjs我找不到它的工作原理。 谁能告诉我,当用户停止输入几秒钟(假设5秒)时,如何调用一个方法(将处理搜索).我不知道在哪里写代码来检查用户是否已经停止输入。
import React, {Component, PropTypes} from 'react';
export default class SearchBox extends Component {
state={
name:" ",
}
changeName = (event) => {
this.setState({name: event.target.value});
}
sendToParent = () => {
this.props.searching(this.state.name);
}
render() {
return (
<div>
<input type="text" placeholder='Enter name you wish to Search.' onChange={this.changeName} />
</div>
);
}
}
我想在用户停止输入时调用sendToParent方法。
你可以使用 setTimeout
关于你的代码,如下:
state = {
name: '',
typing: false,
typingTimeout: 0
}
changeName = (event) => {
const self = this;
if (self.state.typingTimeout) {
clearTimeout(self.state.typingTimeout);
}
self.setState({
name: event.target.value,
typing: false,
typingTimeout: setTimeout(function () {
self.sendToParent(self.state.name);
}, 5000)
});
}
另外,你需要绑定 changeName
在构造函数中使用处理函数。
constructor(props) {
super(props);
this.changeName = this.changeName.bind(this);
}
另一种方式,在我这里是可行的。
class Search extends Component {
constructor(props){
super(props);
this.timeout = 0;
}
doSearch(evt){
var searchText = evt.target.value; // this is the search text
if(this.timeout) clearTimeout(this.timeout);
this.timeout = setTimeout(() => {
//search function
}, 300);
}
render() {
return (
<div className="form-group has-feedback">
<label className="control-label">Any text</label>
<input ref="searchInput" type="text" onChange={evt => this.doSearch(evt)} />
</div>
);
}
}
我认为我们可以用更简单更干净的方式来做,而不需要像这样中断调用整个组件生命周期的状态参数。
constructor(props) {
super(props);
//Timer
this.typingTimeout = null;
//Event
this.onFieldChange = this.onFieldChange.bind(this);
//State
this.state = { searchValue: '' };
}
/**
* Called on the change of the textbox.
* @param {[Object]} event [Event object.]
*/
onFieldChange(event) {
// Clears the previously set timer.
clearTimeout(this.typingTimeout);
// Reset the timer, to make the http call after 475MS (this.callSearch is a method which will call the search API. Don't forget to bind it in constructor.)
this.typingTimeout = setTimeout(this.callSearch, 475);
// Setting value of the search box to a state.
this.setState({ [event.target.name]: event.target.value });
}
<div className="block-header">
<input
type="text"
name="searchValue"
value={this.state.searchValue}
placeholder="User Name or Email"
onChange={this.onFieldChange}
/>
</div>
你可以使用 lodash的debounce或者使用setTimeout模拟。
import React, {Component, PropTypes} from 'react';
export default class SearchBox extends Component {
constructor(props){
super(props);
this.state={ name:" "}
this.timeout = null;
}
changeName = (event) => {
clearTimeout(timeout);
if(timeout){
setTimeout((event)=> this.setState({name: event.target.value}), 200)
}
}
sendToParent = () => {
this.props.searching(this.state.name);
}
render() {
return (
<div>
<input type="text" placeholder='Enter name you wish to Search.' onChange={this.changeName} />
</div>
);
}
}
我使用了lodash的debounce函数
onChangeSearchInput = (evt)=> {
this.debouncedSearch(evt.target.value);
};
debouncedSearch = debounce(function (query) {
this.setState({query});
}, 1000);
在我的渲染方法中的某个地方,我有这个输入字段。
<input
type='text'
onChange={this.onChangeSearchInput}
className='uk-input'
placeholder={'search by name or email...'}
/>
使用useEffect钩子实现。
function Search() {
const [searchTerm, setSearchTerm] = useState('')
useEffect(() => {
const delayDebounceFn = setTimeout(() => {
console.log(searchTerm)
// Send Axios request here
}, 3000)
return () => clearTimeout(delayDebounceFn)
}, [searchTerm])
return (
<input
autoFocus
type='text'
autoComplete='off'
className='live-search-field'
placeholder='Search here...'
onChange={(e) => setSearchTerm(e.target.value)}
/>
)
}
用户 宿雾 javascript库并使用 [_.debounce][1]
changeName: _.debounce(function (val) {
console.log(val)
}, 1000)
这里有一个工作组件模板,有一些有用的参数,可以让你开始使用。
import React, { Component } from 'react'
const initialState = { results: [], value: '' }
export default class SearchBox extends Component {
state = initialState
timeout = null
search_url = "https://example.com/search?q="
min_query_length = 2
timeout_duration = 300
handleSearchChange = (e) => {
let value = e.target.value
clearTimeout(this.timeout);
if (value.length < 1) {
return this.setState(initialState)
} else {
this.setState({ value })
if (value.length>=this.min_query_length) {
this.timeout = setTimeout(this.search, this.timeout_duration);
}
}
}
search = () => {
// assuming your results are returned as JSON
fetch(`${this.search_url}${this.state.value}`)
.then(res => res.json())
.then(data => {
this.setState({
results: data,
})
})
}
render() {
return (
<input
onChange={this.handleSearchChange}
/>
)
}
}
Typeahead库的问题 https:/twitter.github.iotypeahead.js。
由于这里的情况很简单,我可以使用一个快速和肮脏的解决方案。
onChange: (event) ->
if @_timeoutTask?
clearTimeout @_timeoutTask
@_timeoutTask = setTimeout (=>
@sendToParent event.target.value
clearTimeout @_timeoutTask
), 5000
这样,任务将在输入事件发生5秒后被触发。如果有新的事件发生,旧的任务会被取消,新的任务会被安排,然后又要等待5s。
在React中,不同的是计算状态的存储位置,如 _timeoutTask
. 文件范围、组件状态或组件实例。
由于 _timeoutTask
是组件级的,应该是全局存储的,而且不影响渲染,所以不在组件状态。而且它不影响渲染,所以也不在组件状态中。所以我建议直接把它附加到组件实例中。
以上是关于如何在用户停止输入时才开始搜索?的主要内容,如果未能解决你的问题,请参考以下文章