ユーザーが入力を停止したときに検索を実行する必要があります。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>
);
}
}
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>
);
}
}
次のように完全なコンポーネントライフサイクルを呼び出す状態パラメーターを急激に変更することなく、よりシンプルでクリーンな方法でそれを行うことができると思います。
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のデバウンス機能を使用しました
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...'}
/>
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
はコンポーネントレベルであるため、グローバルに保存する必要があります。また、レンダリングには影響しないため、コンポーネントの状態にも影響しません。したがって、コンポーネントインスタンスに直接アタッチすることをお勧めします。
ユーザー lodash javascriptライブラリと[_.debounce][1]
changeName: _.debounce(function (val) {
console.log(val)
}, 1000)
私は反応するために大量のデータを渡すプロジェクトに取り組んでいました。データの量は、各文字を入力した後に遅れを引き起こします。フォームが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