如何立即更新React状态?

时间:2017-06-08 20:44:40

标签: javascript reactjs immutability create-react-app

我所做的功能目的是更新状态并不完美。

我对我修改的当前状态进行了深层复制,然后将状态设置为更改后的副本。我决定在副本上运行一个简单的映射并更新数组中每个对象的属性,这使应用程序立即更新状态并显示更改。 (未在下面的代码中显示,我刚试过的东西)

但它不适用于我真正想要对副本进行的修改。由于setState发生异步,我明白这些更改不会立即发生,我该如何解决?因为第二次触发函数时会看到更改,但我希望它在第一次运行时发生。如果需要,您可以在https://non.mpedersen.me/看到我正在构建的实时演示。

App.js中的功能

addressSearch(address){
    console.log('firing search for distance. Origin is: ' + address)
    let origin = [address];
    const newStores = JSON.parse(JSON.stringify(this.state.stores))
    let service = new google.maps.DistanceMatrixService();

    newStores.map(store => service.getDistanceMatrix({
      origins: origin,
      destinations: store.addressapi,
      travelMode: 'DRIVING',
    }, result => {
      store.distance = result.rows["0"].elements["0"].distance.text.replace(/\Dkm/, '').replace(/,/,'.').replace(/\s/, '');
      store.duration = result.rows["0"].elements["0"].duration.text;
    }))

    newStores.sort((a,b) => a.distance - b.distance);
    this.setState({stores : newStores})
  }

2 个答案:

答案 0 :(得分:4)

完成所有setState并完成地图后,您必须getDistanceMatrix。因为该函数运行异步,所以当你setState时,你并没有真正完成函数的完成。完成发生在另一个堆栈中。

Promise非常好,因为它们有助于处理这样的场景。这是一个非常好的问题,因为它显示了JS机制的本质(事件循环)。

尝试使用此代码,但要知道我没有测试/运行它,如果您明白它会将您带到正确的位置:

  const getDistanceMatrix = (store) => {
    return new Promise((resolve) => {
      service.getDistanceMatrix({
        origins: origin,
        destinations: store.addressapi,
        travelMode: 'DRIVING',
      }, result => {
        store.distance = result.rows["0"].elements["0"].distance.text.replace(/\Dkm/, '').replace(/,/,'.').replace(/\s/, '');
        store.duration = result.rows["0"].elements["0"].duration.text;
        resolve(store)
      })
    })
  }

  addressSearch(address){
    console.log('firing search for distance. Origin is: ' + address)
    let origin = [address];
    const newStores = JSON.parse(JSON.stringify(this.state.stores))
    let service = new google.maps.DistanceMatrixService();

    Promise.all(newStores.map(getDistanceMatrix).then((newStores) => {
      newStores.sort((a,b) => a.distance - b.distance);
      this.setState({stores : newStores})
    })
  }
BTW,解析Promise后异步设置状态可能会导致错误,如果主机组件不再安装。这实际上是采用像redux这样的模式的一个很好的理由,它简化了很多这样的事情!

答案 1 :(得分:0)

这解决了它:)

getDistanceMatrix = (address, store) => {
    return new Promise((resolve) => {
      let service = new google.maps.DistanceMatrixService();
      let origin = [address];
      service.getDistanceMatrix({
        origins: origin,
        destinations: store.addressapi,
        travelMode: 'DRIVING',
      }, result => {
        store.distance = result.rows["0"].elements["0"].distance.text.replace(/\Dkm/, '').replace(/,/,'.').replace(/\s/, '');
        store.duration = result.rows["0"].elements["0"].duration.text;
        resolve(store)
      })
    })
  }

  addressSearch(address){
    console.log('firing search for distance. Origin is: ' + address)
    const newStores = JSON.parse(JSON.stringify(this.state.stores))
    Promise.all(newStores.map(store => this.getDistanceMatrix(address, store))).then(newStore => {
      newStores.sort((a,b) => a.distance - b.distance);
      this.setState({stores : newStores})
    })
  }