reactjs setState没有正确改变

时间:2016-07-24 20:14:02

标签: javascript reactjs

我有一个小反应应用程序。当选定的dep / arr站更改时,它将从BART API中重新获取计划数据。

由于某些原因使用旧代码(见下文),它无法正常工作。我先setState然后尝试使用depStation的新值,但它显示了之前的值。例如,假设我重新加载页面,初始depState值为SFIA。如果我将值更改为FRMT,则console.log(selected)会显示FRMT,但console.log(this.state.depStation)仍显示SFIA。如果我再次将其更改为HAYW,则console.log(selected)显示HAYW,但console.log(this.state.depStation)会显示FRMT。为了使应用程序正常工作,我只是使用了selected而不是this.state.depStation,但我想这不是最佳方法。

所以我真的不明白为什么this.state.depStation在调用this.setState({depStation: selected})后会显示prev数据。能告诉我为什么会这样吗?

旧版本无效:

reRunFetching(selected, type) {
  if (type === "depart") {
    this.setState({depStation: selected});
    console.log(selected); //Showing properly what I select
    console.log(this.state.depStation); //For some reason the previously selected
  }
  else if (type === "arrive") {
    this.setState({arrStation: selected});
  }
  this.fetchingAPI(this.state.depStation, this.state.arrStation)
}

新版本。这工作正常,但我认为这不是最好的解决方案:

reRunFetching(selected, type) {
  if (type === "depart") {
    this.fetchingAPI(selected, this.state.arrStation)
    this.setState({depStation: selected});
    console.log(selected, this.state.arrStation);
  }
  else if (type === "arrive") {
    this.fetchingAPI(this.state.depStation, selected)
    this.setState({arrStation: selected});
    console.log(this.state.depStation, selected);
  }
}

其余的index.js

class App extends Component {
  constructor(props) {
    super(props);

    this.state = {
      schedules: [],
      depStation: DEP_STATION,
      arrStation: ARR_STATION
    };

    this.fetchingAPI(this.state.depStation, this.state.arrStation)
  }

  fetchingAPI(departureStation, arrivalStation) {
    fetch("http://api.bart.gov/api/sched.aspx?cmd=depart&orig=" + departureStation + "&dest=" + arrivalStation + "&date=now&key=MW9S-E7SL-26DU-VV8V&b=0&a=4&l=0")
    .then(function(response) {
        return response.text();})
    .then((responseXML) => {
      let tripsArray = this.parsingXML(responseXML);
      this.setState({schedules: tripsArray});
    })
    .catch((error) => {
      console.log(error);
    });
  }

  render () {
    return (
      <div>
        <div className="row">
          <div className="col-md-5 col-md-offset-1 search-bar">
            <SelectDepart onSelectedChange={selected => this.reRunFetching(selected, "depart")}/>
          </div>
          <div className="col-md-5 search-bar">
            <SelectArrive onSelectedChange={selected => this.reRunFetching(selected, "arrive")}/>
          </div>
        </div>
        <TimeTable schedules={this.state.schedules} />
      </div>
    )
  }

2 个答案:

答案 0 :(得分:1)

setState()是一种异步非阻塞方法,它不会像您期望的那样立即设置新状态。正如官方文档所说:

  

setState()不会立即改变this.state,但会创建挂起状态转换。调用此方法后访问this.state可能会返回现有值   无法保证对setState的调用进行同步操作,并且可以对调用进行批处理以获得性能提升。

如果需要,可以将回调传递给setState()的第二个参数,它将在状态更改时触发:

this.setState({depStation: selected}, function() {
// some code
});

答案 1 :(得分:0)

setState()是一个对您的状态进行排队的异步方法。所以为了在setState之后立即访问状态值,你需要调用一个回调函数作为setState方法的第二个参数,它将首先设置你的状态,之后将重新呈现你的视图更新状态。以下示例将帮助您。

<tablename>