Поиск в реале, когда пользователь перестает печатать

Мне нужно выполнить поиск, когда пользователь перестает печатать. Я знаю, что я должен использовать 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, когда пользователь перестает печатать.

Ответ 1

Вы можете использовать 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 обработчик changeName в конструкторе.

constructor(props) {
   super(props);
   this.changeName = this.changeName.bind(this);
}

Ответ 2

Другой способ, который работал со мной:

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>
    );
  }
}

Ответ 3

Проблема библиотеки Typeahead https://twitter.github.io/typeahead.js/

Поскольку случай здесь прост, я могу использовать быстрое и грязное решение:

onChange: (event) ->
  if @_timeoutTask?
    clearTimeout @_timeoutTask

  @_timeoutTask = setTimeout (=>
    @sendToParent event.target.value
    clearTimeout @_timeoutTask
  ), 5000

Таким образом, задача будет инициирована через 5 секунд после ввода. Если произойдет новое событие, старая задача будет отменена и запланирована новая задача, а затем еще 5 секунд ожидания.

Разница в реактиве - это место хранения состояния вычисления, например _timeoutTask. Область файла, состояние компонента или экземпляр компонента.

Так как _timeoutTask является уровнем компонента, он должен храниться глобально. И это не влияет на рендеринг, поэтому не в состоянии компонента тоже. Поэтому я предлагаю напрямую связать его с экземпляром компонента.

Ответ 4

вы можете просто использовать debounce из lodash или имитировать с помощью 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>
        );
    }
}

Ответ 5

Я думаю, что мы можем сделать это более простым и чистым способом, не прерывая параметр состояния, который вызывает полный жизненный цикл компонента, как это:

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>

Ответ 6

Пользовательская библиотека lodash javascript и использование [_.debounce][1]

changeName: _.debounce(function (val) {
  console.log(val)                
}, 1000)