更新文本输入状态和AJAX搜索的相同值滞后一个字符

时间:2017-09-03 18:06:21

标签: javascript reactjs

我有一个文本输入搜索栏来查找产品,当我键入时,它会发出一个AJAX请求来查找匹配项并将其设置为产品状态。但是,它落后于一个角色。 IE我键入" car"它正在搜索" ca",当我输入"汽车"它用" car"进行搜索。我猜它与React setState的工作原理有关。关于如何解决这个问题的提示?

class ProductIndexPage extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      term: '',
      collection: null,
      products: this.props.products
    };
    this.handleChange = this.handleChange.bind(this);
  }
  handleChange(event) {
    this.setState({term: event});
    this.searchProducts()
  }
  render() {
    function CreateItem(product) {
      return { 
        url: '/products/' + product.id, 
        attributeOne: product.title,
        attributeTwo: product.variants[0].variant_price,
        attributeThree: '5 prices from $8.99 to $13.99',
        media: <Thumbnail
                  source={product.main_image_src}
                  alt={product.title}
                  size="small"
                />
      }
    }
    function CollectionTitles(collection) {
      return collection.title
    }
    return (
      <Layout>
        <Layout.Section>
          <Card title="Online store dashboard" actions={[{content: 'Edit'}]} sectioned>
            <Card.Section>
              <Stack>
                <TextField 
                  value={this.state.term}
                  label="Keyword Search"
                  placeholder="Enter Term"
                  onChange={this.handleChange}
                />
                <Select
                  value= {this.state.collection}
                  label="Collection"
                  options={ this.props.collections.map(CollectionTitles) }
                  placeholder="Select"
                  //onChange={this.valueUpdater('collection')}
                  //onChange={this.searchProducts('collection')}
                />
              </Stack>
            </Card.Section>
            <Card.Section>
                <ResourceList
                  items={
                      this.state.products.map(CreateItem)
                  }
                  renderItem={(item, index) => {
                    return <ResourceList.Item key={index} {...item} className='Polaris-Card' />;
                  }}
                />
            </Card.Section>
          </Card>
        </Layout.Section>
      </Layout>
    ); 
  }
searchProducts() {
  console.log('In queryProducts');
  console.log('AJAX')
  $.ajax( {
    url: '/products/' + "?term=" + this.state.term, //+ "&collection=" + this.state.collection,
    dataType: 'json',
    success: function(data) {
      console.log('SUCCESS');
      console.log(data)
    this.setState({ products: data });
    }.bind(this),
    error: function(data) {
    }.bind(this)
   });
}

1 个答案:

答案 0 :(得分:2)

那是因为setState函数是异步的。因此,当您致电setState时,它不会立即设置状态。你在调用setState之后立即调用api调用(即当状态尚未更新时)。这就是为什么它在没有最后一封信的情况下调用api。

解决方案::将回调函数传递给setState。当状态更新时将调用该回调。在那个回调你可以像这样打电话给你的api

handleChange(event) {
    this.setState({term: event}, () => {
      this.searchProducts()
    });
  }