Javascript 如何设置事件onChange的超时

Javascript 如何设置事件onChange的超时,javascript,reactjs,settimeout,inputbox,Javascript,Reactjs,Settimeout,Inputbox,我有一个展示图片的图库,还有一个搜索文本框 Im尝试使用输入超时事件来阻止对Im键入的每个字母进行api调用: 我尝试用doSearch函数onChange处理事件:但现在我无法在文本框中写入任何内容,这会导致许多错误 已将应用程序和库组件附加到此会话 提前谢谢 class App extends React.Component { static propTypes = { }; constructor() { super(); this.timeout = 0;

我有一个展示图片的图库,还有一个搜索文本框 Im尝试使用输入超时事件来阻止对Im键入的每个字母进行api调用: 我尝试用doSearch函数onChange处理事件:但现在我无法在文本框中写入任何内容,这会导致许多错误 已将应用程序和库组件附加到此会话

提前谢谢

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;
类应用程序扩展了React.Component{
静态类型={
};
构造函数(){
超级();
此值为0.timeout;
此.state={
标签:“艺术”
};
}
doSearch(事件){
var searchText=event.target.value;//这是搜索文本
if(this.timeout)cleartimout(this.timeout);
this.timeout=setTimeout(函数(){this.setState({tag:event.target.value}}),500);
}
render(){
返回(
画廊
this.doSearch(event)}value={this.state.tag}/>
);
}
}
导出默认应用程序;
这是画廊课程:

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.com/';
    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});
        }
      });
  }

  componentDidMount() {
    this.getImages(this.props.tag);
    this.setState({
      galleryWidth: document.body.clientWidth
    });
  }

  componentWillReceiveProps(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>
    );
  }
}
从“React”导入React;
从“道具类型”导入道具类型;
从“axios”导入axios;
从“../Image”导入图像;
导入“/Gallery.scss”;
类库扩展了React.Component{
静态类型={
标记:PropTypes.string
};
建造师(道具){
超级(道具);
此.state={
图像:[],
galleryWidth:this.getGalleryWidth()
};
}
getGalleryWidth(){
试一试{
返回document.body.clientWidth;
}捕获(e){
返回1000;
}
}
getImages(标签){
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`;
常量baseUrl=https://api.flickr.com/';
axios({
url:getImagesUrl,
baseURL:baseURL,
方法:“获取”
})
.然后(res=>res.data)
。然后(res=>{
如果(
res&&
照片&&
照片&&
res.photos.photo.length>0
) {
this.setState({images:res.photos.photo});
}
});
}
componentDidMount(){
this.getImages(this.props.tag);
这是我的国家({
galleryWidth:document.body.clientWidth
});
}
组件将接收道具(道具){
this.getImages(props.tag);
}
render(){
返回(
{this.state.images.map((dto,i)=>{
返回;
})}
);
}
}

这是因为您没有将
绑定到您的方法

将以下内容添加到构造函数中:

this.doSearch = this.doSearch.bind(this);

另外,对于
onChange
,您不需要胖箭头符号。只要做:

onChange={this.doSearch}

onChange
处理程序很好,但是您需要绑定
setTimeout
来呈现上下文。目前,它指的是窗口上下文。代码如下

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

首先,为什么需要使用setTimeout来设置用户输入的值。在doSearch函数中使用setTimeout没有任何用处

doSearch函数无法工作的原因是您没有绑定它

您可以通过以下方式使用doSearch函数中的setState直接将值设置为tag

ES5路

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

doSearch(event){
    this.setState({
       tag: event.target.value
    });
}
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);
}
ES6路

doSearch = (event) => {
    this.setState({
       tag: event.target.value
    });
}
在doSearch函数中的setTimeout内执行setState将不起作用,因为 输入标记已指定值

ES5路

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

doSearch(event){
    this.setState({
       tag: event.target.value
    });
}
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);
}
以ES6方式设置超时

doSearch = (event) => {
     if(this.timeout) clearTimeout(this.timeout);
     this.timeout = setTimeout(() => {
       this.setState({
          tag: event.target.value
       }) 
     },500);
}
库组件:

将当前道具更改与组件中以前的更改一起检查将接收道具,以避免额外渲染

尝试以下更新的代码

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.com/';
    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});
        }
      });
  }

  componentDidMount() {
    this.getImages(this.props.tag);
    this.setState({
      galleryWidth: document.body.clientWidth
    });
  }

  componentWillReceiveProps(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>
    );
  }
}
从“React”导入React;
从“道具类型”导入道具类型;
从“axios”导入axios;
从“../Image”导入图像;
导入“/Gallery.scss”;
类库扩展了React.Component{
静态类型={
标记:PropTypes.string
};
建造师(道具){
超级(道具);
此.state={
图像:[],
galleryWidth:this.getGalleryWidth()
};
}
getGalleryWidth(){
试一试{
返回document.body.clientWidth;
}捕获(e){
返回1000;
}
}
getImages(标签){
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`;
常量baseUrl=https://api.flickr.com/';
axios({
url:getImagesUrl,
baseURL:baseURL,
方法:“获取”
})
.然后(res=>res.data)
。然后(res=>{
如果(
res&&
照片&&
照片&&
res.photos.photo.length>0
) {
this.setState({images:res.photos.photo});
}
});
}
componentDidMount(){
this.getImages(this.props.tag);
这是我的国家({
galleryWidth:document.body.clientWidth
});
}
组件将接收道具(下一步){
if(nextrops.tag!=this.props.tag){
this.getImages(props.tag);
}
}
shouldComponentUpdate(下一步,下一步状态){
if(this.props.tag==nextrops.tag){
返回false;
}否则{
返回true;
}
}
render(){
返回(
{this.state.images.map((dto,i)=>{
返回;
})}
);
}
}
我将标记初始值保留为空,因为您没有使用价值艺术进行任何操作

请尝试以下代码

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;
类应用程序扩展了React.Component{
静态类型={
};
构造函数(){
超级();
此值为0.timeout;
此.state={
标记:“”,
callGallery:错误
};
}
doSearch=(事件)=>{
this.setState({tag:event.target.value,callGallery:false});
}
handleSearch=()=>{
这是我的国家({
真的吗
});
}
render(){
返回(
画廊
this.doSearch(event)}value={this.state.tag}/>
{this.state.callGallery&&}
);
}
}
导出默认应用程序;

只需更换您通过的功能