私はReactJSを学んでいて、次の問題で立ち往生しています。連絡先検索の入力があり、ユーザーが入力を停止してから1000ミリ秒後にそれを処理したいと考えています。私はこの目的のためにデバウンス機能を使用します:
import React, { Component} from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import {debounce} from 'lodash';
const contacts = [
{
id: 1,
name: 'Darth Vader',
phoneNumber: '+250966666666',
image: 'img/darth.gif'
}, {
id: 2,
name: 'Princess Leia',
phoneNumber: '+250966344466',
image: 'img/leia.gif'
}, {
id: 3,
name: 'Luke Skywalker',
phoneNumber: '+250976654433',
image: 'img/luke.gif'
}, {
id: 4,
name: 'Chewbacca',
phoneNumber: '+250456784935',
image: 'img/chewbacca.gif'
}
];
class Contact extends React.Component {
render() {
return (
<li className="contact">
<img className="contact-image" src={this.props.image} width="60px" height="60px"/>
<div className="contact-info">
<div className="contact-name">{this.props.name}</div>
<div className="contact-number">{this.props.phoneNumber}</div>
</div>
</li>
);
}
}
class ContactList extends React.Component {
constructor(props) {
super(props);
this.state = {
displayedContacts: contacts,
};
this.handleChange = debounce(this.handleChange.bind(this), 1000);
}
handleChange = e => {
e.persist();
let input = e.target.value.toLowerCase();
this.setState({
displayedContacts: contacts.filter(c => c.name.toLowerCase().includes(input))
});
}
render() {
return (
<div className="contacts">
<input type="text" className="search-field" onChange={this.handleChange}/>
<ul className="contacts-list">
{
this.state.displayedContacts.map(c =>
<Contact
key={c.id}
name={c.name}
phoneNumber={c.phoneNumber}
image={c.image} />
)
}
</ul>
</div>
);
}
}
ReactDOM.render(
<ContactList />,
document.getElementById('root')
);
検索入力を入力した後、コンソールログにwarningが表示されます。この合成イベントは、パフォーマンス上の理由で再利用されます。これが表示されている場合、リリース済み/無効化された合成イベントのプロパティtarget
にアクセスしています。これはnullに設定されています。元の合成イベントを保持する必要がある場合は、event.persist()を使用してください "
およびerror "キャッチされていないTypeError:ContactList._this2.handleChangeでnullのプロパティ 'value'を読み取れません。
persist
関数でhandleChange
メソッドを使用しています。このエラーが発生するのはなぜですか?
イベントハンドラーは同期的に実行するのが最適です。 value
を個別に処理し、別のデバウンス関数で連絡先をフィルタリングできます。
例
class ContactList extends React.Component {
state = {
contacts,
displayedContacts: contacts
};
setDisplayedContacts = debounce(query => {
this.setState({
displayedContacts: this.state.contacts.filter(c =>
c.name.toLowerCase().includes(query)
)
});
}, 1000);
handleChange = e => {
let input = e.target.value.toLowerCase();
this.setDisplayedContacts(input);
};
render() {
return (
<div className="contacts">
<input
type="text"
className="search-field"
onChange={this.handleChange}
/>
<ul className="contacts-list">
{this.state.displayedContacts.map(c => (
<Contact
key={c.id}
name={c.name}
phoneNumber={c.phoneNumber}
image={c.image}
/>
))}
</ul>
</div>
);
}
}