web-dev-qa-db-ja.com

ユーザーが入力を停止したときにReactで検索

ユーザーが入力を停止したときに検索を実行する必要があります。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メソッドを呼び出したい。

27
shinite

次のように、コードに関して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);
}
37
Saba Hassan

私と一緒に働いた別の方法:

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>
    );
  }
}
16
Ninh Ngo

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>
        );
    }
}
4
Khalid Azam

次のように完全なコンポーネントライフサイクルを呼び出す状態パラメーターを急激に変更することなく、よりシンプルでクリーンな方法でそれを行うことができると思います。

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>
3
Rahul

Lodashのデバウンス機能を使用しました

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...'}
   />
2

Typeaheadライブラリの問題 https://Twitter.github.io/typeahead.js/

ここのケースは単純なので、私は迅速で汚い解決策を使用できます。

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

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

このようにして、タスクは入力イベントの5秒後にトリガーされます。新しいイベントが発生した場合、古いタスクはキャンセルされ、新しいタスクがスケジュールされます。その後、さらに5秒待ちます。

Reactの違いは、_timeoutTaskのような計算状態を保存する場所です。ファイルスコープ、コンポーネント状態、またはコンポーネントインスタンスです。

_timeoutTaskはコンポーネントレベルであるため、グローバルに保存する必要があります。また、レンダリングには影響しないため、コンポーネントの状態にも影響しません。したがって、コンポーネントインスタンスに直接アタッチすることをお勧めします。

0
jiyinyiyong

ユーザー lodash javascriptライブラリと[_.debounce][1]

changeName: _.debounce(function (val) {
  console.log(val)                
}, 1000)
0
Amir Ur Rehman

私は反応するために大量のデータを渡すプロジェクトに取り組んでいました。データの量は、各文字を入力した後に遅れを引き起こします。フォームが5つの異なるタブに広がっていて、タブを切り替えると入力値が失われたため、制御されていない入力を使用できませんでした。これは私が持っていた状況の一種です。解決策は、すべての文字が入力された後ではなく、ユーザーが入力を停止した後に状態を更新することです。それを実現するために、制御される入力と制御されない入力の2つのタイプを使用できます。

https://github.com/Pyot/react-update-state-on-stop-typing および以下のコード例のいずれかが役立つ場合があります。

import React, { Component } from 'react'

class ForHeavyData extends Component {
  state = {
    value: ''
  }

  timer = null

  handleChange = (e) => {
    clearTimeout(this.timer);
    let value = e.target.value;
    this.timer = setTimeout(() => { this.triggerChange(value) }, 2000);
  }

  triggerChange = (targetValue) => {
    this.setState({ value: targetValue })
  }

render() {

return (
  <div className={'container'}>
    <div className={'row'}>
      <div className={'col-md-6'}>
        <div className={"form-group"}>
          <label forHtml="exampleInputEmail1"></label>
          <input
            className={'form-control'}
            placeholder={'Please type text...'}
            defaultValue={this.state.value}
            onChange={this.handleChange}
            onKeyDown={this.handleKeyDown} />
          <small className={"form-text text-muted"}>You'll see what you type after 2sec when you stop typing below.</small>
        </div>
      </div>
    </div>
    <div className={'row'}>
      <div className={'col-md-6'}>
        <div className={'redborder'}>
          {this.state.value !== '' ? this.state.value : 'You will see updated state here'}
        </div>
      </div>
    </div>
  </div>
)
}
}
export default ForHeavyData
0
Pyot