如何立即更新我的 React 状态?

How do I make my React state update immediately?

我创建的用于更新状态的功能无法完美运行。

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

但它不适用于我真正想对副本进行的修改。由于 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})
  }

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

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

试试这个代码,但要知道我还没有 tested/runned,如果你明白了,它将带你到正确的地方:

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

顺便说一句,如果不再安装主机组件,则在解决 Promise 后异步设置状态可能会导致错误。这实际上是采用像 redux 这样的模式的一个很好的理由,它简化了很多这样的事情!

这解决了:)

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