如何仅在用户停止输入时开始搜索?

IT技术 reactjs settimeout
2021-04-02 03:57:38

当用户停止输入时,我需要执行搜索。我知道我应该使用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 方法。

6个回答

您可以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);
}
出于同样的原因,您不需要设置const self = this. this已经绑定到类范围。
2021-05-25 03:57:38
打字状态的领域有必要吗?
2021-05-30 03:57:38
我迟到了,但我想指出的是,在使用 es6 箭头语法时,您不需要绑定 changeName 函数。developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
2021-06-02 03:57:38
打字字段看起来没有必要。当你使用箭头函数时changeName,你不需要this在构造函数中绑定
2021-06-15 03:57:38
有一个拼写错误:``` state = { ... typingTimeOut: 0 } ```typingTimeout 是用大写的 O 写的。无法编辑答案以修复拼写错误。
2021-06-16 03:57:38

使用 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)}
    />
  )
}
@AljohnYamaro,你能解释一下为什么它会被重新渲染吗?
2021-05-25 03:57:38
制作了一个代码沙盒,以防万一有任何帮助代码和盒子.io/s/search-input-settimeout-wszrv?file=/src/...
2021-05-29 03:57:38
小心,这将重新渲染组件
2021-05-31 03:57:38
可惜@AljohnYamaro 被忽略了。他说得很好
2021-06-10 03:57:38
简单而迷人。此解决方案需要更多投票
2021-06-17 03:57:38

另一种与我合作的方式:

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>
    );
  }
}
这工作正常,直到我将值作为输入字段的状态..
2021-06-06 03:57:38
我得到了这个工作,但它仍然搜索第一个字母
2021-06-07 03:57:38

我使用了 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...'}
   />
@w3debugger 你是对的。但是我的项目中已经有 lodash 用于其他用途。
2021-05-26 03:57:38
您也可以只导入一个特定的函数,而不是拉入整个库。
2021-06-12 03:57:38
仅仅为了延迟一个函数而调用一个全新的(巨大的)库是不好的,对吧?
2021-06-14 03:57:38

我认为我们可以以更简单、更简洁的方式来完成,而无需像这样中断调用完整组件生命周期的状态参数:

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>