如何设置事件onChange的超时

2022-04-03 00:00:00 reactjs javascript settimeout inputbox
我有一个显示图像的图库,还有一个搜索文本框 我正在尝试在输入事件上使用超时,以防止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;

这是Gallery类:

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

解决方案

首先,为什么需要使用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
    });
}

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){
     if(this.timeout) clearTimeout(this.timeout);
     this.timeout = setTimeout(function(){
       this.setState({
          tag: event.target.value
       }) 
     }.bind(this),500);
}

ES6方式的setTimeout

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

图库组件:

使用ComponentWillRecieveProps中以前的更改检查当前道具更改,以避免额外的渲染。

尝试使用以下更新的代码

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

我将标记初始值保持为空,因为您没有使用价值艺术进行任何操作。

请尝试使用以下代码

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;

相关文章