当查询为空时显示的项目

时间:2018-05-29 12:49:48

标签: javascript reactjs ecmascript-next

我正在学习反应,我已经使用freecodecamp的示例制作了一个示例电视节目应用程序。从我所能看到的一切都工作正常但是在搜索了一些内容然后在搜索框中退回所有内容后,它显示了结果,当它不应该是,有人能看到我在我的代码中犯了错误吗?

class SeriesList extends React.Component {
  state = {
    series: [],
    query: ''
  }

  onChange = async e => {
    this.setState({query: e.target.value});
    const response = await fetch(
      `https://api.tvmaze.com/search/shows?q=${this.state.query}`
    );
    const data = await response.json();
    this.setState({series: data});
  }

  render(){
    return (
      <div>
        <input type="text" onChange={this.onChange} value={this.state.query} />
        <ul>
          <SeriesListItem list={this.state.series} />
        </ul>
      </div>
    );
  }
}

我在codepen上有这个。

https://codepen.io/crash1989/pen/ERxPGO

感谢

3 个答案:

答案 0 :(得分:1)

setState工作异步。因此,无法保证在调用this.state.querythis.setState({query: e.target.value})已更新。所以你的网址最终会包含以前的状态。

有两种选择:

  1. 使用新查询的事件数据:

    const response = await fetch(
       `https://api.tvmaze.com/search/shows?q=${e.target.value}`
    );
    ...
    
  2. 使用setState回调第二个arg

    this.setState({query: e.target.value}, () => {
      const response = await fetch(
        `https://api.tvmaze.com/search/shows?q=${this.state.query}`
      );
      ...
    })
    
  3. 这是一篇关于setState https://medium.com/@wereHamster/beware-react-setstate-is-asynchronous-ce87ef1a9cf3的异步性质的好文章。

答案 1 :(得分:1)

另外一点你可以使用await for setState

onChange = async e => {    
    await this.setState({query: e.target.value});
    const response = await fetch(
      `https://api.tvmaze.com/search/shows?q=${this.state.query}`
    );
    const data = await response.json();
    this.setState({series: data});
  }

您的请求将在更改查询后执行

答案 2 :(得分:0)

问题

存在竞争条件:当您键入两个+字母时,您可以进行两次+网络呼叫。第一个网络呼叫可能是最后一个完成,然后您显示错误查询的结果。

我用这支笔修好了它:https://codepen.io/arnemahl/pen/zaYNxv

解决方案

跟踪您收到回复的所有查询的结果。始终如何为当前查询返回数据。 (另外,不要为同一个查询进行多次API调用,我们已经知道了。)

state: {
  seriesPerQuery: {}, // Now a map with one result for each query you look up
  query: [],
}

...

onChange = async e => {
  ...

  // Now keep the results of the old querys, in addition to the new one
  // whenever you get an API response
  this.setState(state => ({
    seriesPerQuery: {
      ...state.seriesPerQuery,
      [query]: data,
    }
  }));
}