admin管理员组文章数量:1310221
I have a gallery that show images, and i have a search textbox Im Trying to use Timeout on Input event to prevent the api call on every letter im typing : I try to handle the event with doSearch function onChange: but now I cant write anything on the textbox and it cause many errors Attached to this session the app and gallery ponents
Thanks in advance
class App extends React.Component {
static propTypes = {
};
constructor() {
super();
this.timeout = 0;
this.state = {
tag: 'art'
};
}
doSearch(event){
var searchText = event.target.value; // this is the search text
if(this.timeout) clearTimeout(this.timeout);
this.timeout = setTimeout(function(){this.setState({tag: event.target.value})} , 500);
}
render() {
return (
<div className="app-root">
<div className="app-header">
<h2>Gallery</h2>
<input className="input" onChange={event => this.doSearch(event)} value={this.state.tag}/>
</div>
<Gallery tag={this.state.tag}/>
</div>
);
}
}
export default App;
This is the Gallery class:
import React from 'react';
import PropTypes from 'prop-types';
import axios from 'axios';
import Image from '../Image';
import './Gallery.scss';
class Gallery extends React.Component {
static propTypes = {
tag: PropTypes.string
};
constructor(props) {
super(props);
this.state = {
images: [],
galleryWidth: this.getGalleryWidth()
};
}
getGalleryWidth(){
try {
return document.body.clientWidth;
} catch (e) {
return 1000;
}
}
getImages(tag) {
const getImagesUrl = `services/rest/?method=flickr.photos.search&api_key=522c1f9009ca3609bcbaf08545f067ad&tags=${tag}&tag_mode=any&per_page=100&format=json&safe_search=1&nojsoncallback=1`;
const baseUrl = '/';
axios({
url: getImagesUrl,
baseURL: baseUrl,
method: 'GET'
})
.then(res => res.data)
.then(res => {
if (
res &&
res.photos &&
res.photos.photo &&
res.photos.photo.length > 0
) {
this.setState({images: res.photos.photo});
}
});
}
ponentDidMount() {
this.getImages(this.props.tag);
this.setState({
galleryWidth: document.body.clientWidth
});
}
ponentWillReceiveProps(props) {
this.getImages(props.tag);
}
render() {
return (
<div className="gallery-root">
{this.state.images.map((dto , i) => {
return <Image key={'image-' + dto.id+ i.toString()} dto={dto} galleryWidth={this.state.galleryWidth}/>;
})}
</div>
);
}
}
I have a gallery that show images, and i have a search textbox Im Trying to use Timeout on Input event to prevent the api call on every letter im typing : I try to handle the event with doSearch function onChange: but now I cant write anything on the textbox and it cause many errors Attached to this session the app and gallery ponents
Thanks in advance
class App extends React.Component {
static propTypes = {
};
constructor() {
super();
this.timeout = 0;
this.state = {
tag: 'art'
};
}
doSearch(event){
var searchText = event.target.value; // this is the search text
if(this.timeout) clearTimeout(this.timeout);
this.timeout = setTimeout(function(){this.setState({tag: event.target.value})} , 500);
}
render() {
return (
<div className="app-root">
<div className="app-header">
<h2>Gallery</h2>
<input className="input" onChange={event => this.doSearch(event)} value={this.state.tag}/>
</div>
<Gallery tag={this.state.tag}/>
</div>
);
}
}
export default App;
This is the Gallery class:
import React from 'react';
import PropTypes from 'prop-types';
import axios from 'axios';
import Image from '../Image';
import './Gallery.scss';
class Gallery extends React.Component {
static propTypes = {
tag: PropTypes.string
};
constructor(props) {
super(props);
this.state = {
images: [],
galleryWidth: this.getGalleryWidth()
};
}
getGalleryWidth(){
try {
return document.body.clientWidth;
} catch (e) {
return 1000;
}
}
getImages(tag) {
const getImagesUrl = `services/rest/?method=flickr.photos.search&api_key=522c1f9009ca3609bcbaf08545f067ad&tags=${tag}&tag_mode=any&per_page=100&format=json&safe_search=1&nojsoncallback=1`;
const baseUrl = 'https://api.flickr./';
axios({
url: getImagesUrl,
baseURL: baseUrl,
method: 'GET'
})
.then(res => res.data)
.then(res => {
if (
res &&
res.photos &&
res.photos.photo &&
res.photos.photo.length > 0
) {
this.setState({images: res.photos.photo});
}
});
}
ponentDidMount() {
this.getImages(this.props.tag);
this.setState({
galleryWidth: document.body.clientWidth
});
}
ponentWillReceiveProps(props) {
this.getImages(props.tag);
}
render() {
return (
<div className="gallery-root">
{this.state.images.map((dto , i) => {
return <Image key={'image-' + dto.id+ i.toString()} dto={dto} galleryWidth={this.state.galleryWidth}/>;
})}
</div>
);
}
}
Share
Improve this question
edited Aug 15, 2018 at 11:46
ShiGi
asked Aug 15, 2018 at 9:01
ShiGiShiGi
912 gold badges3 silver badges7 bronze badges
1
-
Just replace the function you're passing to
setTimeout
with an arrow function (setTimeout(() => this.setState(...))
) to preserve lexical scope. – haim770 Commented Aug 15, 2018 at 9:09
3 Answers
Reset to default 2First of all why do you need to use setTimeout to set value that is entered by user. I don't see any use using setTimeout in doSearch function.
The reason your doSearch function won't work because you are not binding it.
You can directly set value to tag using setState in doSearch function in following ways.
ES5 way
constructor(props){
super(props);
this.doSearch = this.doSearch.bind(this);
}
doSearch(event){
this.setState({
tag: event.target.value
});
}
ES6 way
doSearch = (event) => {
this.setState({
tag: event.target.value
});
}
Doing setState inside setTimeout in doSearch function won't work because input tag has value assigned.
ES5 way
constructor(props){
super(props);
this.doSearch = this.doSearch.bind(this);
}
doSearch(event){
if(this.timeout) clearTimeout(this.timeout);
this.timeout = setTimeout(function(){
this.setState({
tag: event.target.value
})
}.bind(this),500);
}
setTimeout in ES6 way
doSearch = (event) => {
if(this.timeout) clearTimeout(this.timeout);
this.timeout = setTimeout(() => {
this.setState({
tag: event.target.value
})
},500);
}
Gallery ponent:
Check current props changes with previous change in ponentWillRecieveProps to avoid extra renderings.
Try with below updated code
import React from 'react';
import PropTypes from 'prop-types';
import axios from 'axios';
import Image from '../Image';
import './Gallery.scss';
class Gallery extends React.Component {
static propTypes = {
tag: PropTypes.string
};
constructor(props) {
super(props);
this.state = {
images: [],
galleryWidth: this.getGalleryWidth()
};
}
getGalleryWidth(){
try {
return document.body.clientWidth;
} catch (e) {
return 1000;
}
}
getImages(tag) {
const getImagesUrl = `services/rest/?method=flickr.photos.search&api_key=522c1f9009ca3609bcbaf08545f067ad&tags=${tag}&tag_mode=any&per_page=100&format=json&safe_search=1&nojsoncallback=1`;
const baseUrl = 'https://api.flickr./';
axios({
url: getImagesUrl,
baseURL: baseUrl,
method: 'GET'
})
.then(res => res.data)
.then(res => {
if (
res &&
res.photos &&
res.photos.photo &&
res.photos.photo.length > 0
) {
this.setState({images: res.photos.photo});
}
});
}
ponentDidMount() {
this.getImages(this.props.tag);
this.setState({
galleryWidth: document.body.clientWidth
});
}
ponentWillReceiveProps(nextProps) {
if(nextProps.tag != this.props.tag){
this.getImages(props.tag);
}
}
shouldComponentUpdate(nextProps, nextState) {
if(this.props.tag == nextProps.tag){
return false;
}else{
return true;
}
}
render() {
return (
<div className="gallery-root">
{this.state.images.map((dto , i) => {
return <Image key={'image-' + dto.id+ i.toString()} dto={dto} galleryWidth={this.state.galleryWidth}/>;
})}
</div>
);
}
}
I am keeping tag initial value to empty as you are not doing anything with value art.
Please try with below code
class App extends React.Component {
static propTypes = {
};
constructor() {
super();
this.timeout = 0;
this.state = {
tag: '',
callGallery: false
};
}
doSearch = (event) => {
this.setState({tag: event.target.value, callGallery: false});
}
handleSearch = () => {
this.setState({
callGallery: true
});
}
render() {
return (
<div className="app-root">
<div className="app-header">
<h2>Gallery</h2>
<input className="input" onChange={event => this.doSearch(event)} value={this.state.tag}/>
<input type="button" value="Search" onClick={this.handleSearch} />
</div>
{this.state.callGallery && <Gallery tag={this.state.tag}/>}
</div>
);
}
}
export default App;
onChange
handler is just fine but you need to bind the setTimeout
to render context.Currently,it is referring to window context.And the code as follows
doSearch(event){
var searchText = event.target.value; // this is the search text
if(this.timeout) clearTimeout(this.timeout);
this.timeout = setTimeout(function(){
this.setState({
tag: event.target.value
})
}.bind(this),500);
}
This is because you haven't bound this
to your method.
Add the following to your constructor:
this.doSearch = this.doSearch.bind(this);
Also, you don't need the fat arrow notation for onChange
. Just do:
onChange={this.doSearch}
本文标签: javascriptHow to set timeout on event onChangeStack Overflow
版权声明:本文标题:javascript - How to set timeout on event onChange - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741845670a2400763.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论