简体   繁体   English

如何立即更新React状态?

[英]How do I make my React state update immediately?

The function I've made which purpose is to update state does not work perfectly. 我所做的功能是更新状态的功能并不完美。

I make a deep copy of my current state which I modify, then I set the state to that changed copy. 我对我修改的当前状态进行了深层复制,然后将状态设置为更改后的副本。 I decided to run a simple map on the copy and update a property on each object in the array, this made the app update state immediately and show the changes. 我决定在副本上运行一个简单的映射并更新数组中每个对象的属性,这使应用程序立即更新状态并显示更改。 (not shown in the code below, something I just tried) (未在下面的代码中显示,我刚试过的东西)

But it does not work with the modifications I truly want to make to the copy. 但它不适用于我真正想要对副本进行的修改。 Since the setState happens async, I understand that the changes don't happen immediately, how could I solve this? 由于setState发生异步,我明白这些更改不会立即发生,我该如何解决? Because the changes are seen when the function is triggered a second time, but I want it to happen on the first run. 因为第二次触发函数时会看到更改,但我希望它在第一次运行时发生。 You could see a live demo of what I'm building at https://non.mpedersen.me/ if you want. 如果需要,您可以在https://non.mpedersen.me/上看到我正在构建的实时演示。

Function in App.js 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})
  }

You must setState after all getDistanceMatrix are finished and your map is done. 在所有getDistanceMatrix完成并且您的地图完成后,您必须设置setState Because that function runs async, you are not really getting the function completion when you setState . 因为该函数运行异步,所以在setState时你并没有真正完成函数的完成。 The completion happens in another stack. 完成发生在另一个堆栈中。

Promises are really good because they help dealing with scenarios like this. 承诺非常好,因为它们有助于处理这样的场景。 This is a really nice question because it shows the nature of JS mechanisms (event-loop). 这是一个非常好的问题,因为它显示了JS机制(事件循环)的本质。

Try this code but know that I haven't tested/runned it, if you get the idea it will get you to the right place: 试试这段代码,但要知道我没有测试/运行它,如果你明白它会把你带到正确的地方:

  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, setting state asynchronously after a Promise is resolved may lead to errors if the host component is not mounted anymore. 顺便说一句,在解决Promise之后异步设置状态可能会导致错误,如果主机组件不再安装。 That's actually an excellent reason to adopt a pattern like redux, it simplifies things like this a lot! 这实际上是采用像redux这样的模式的一个很好的理由,它简化了这样的事情!

This solved it :) 这解决了:)

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在 React js 中立即更新状态值? - How can I update state value immediately in React js? 如何在功能组件中立即更新反应状态? - How to update react state immediately in functional component? 如何在 React 功能组件中立即更新状态? - How to update the state immediately in React functional component? 如何在 React 中立即更新 setState - How to make setState update immediately in React 如何在 React 中更新我的 state 数组而不更新 function - How do I update my state array without having update function in React 如何更新 state 与 axios 对我的 React 应用程序提出请求? (反应/节点快递) - How do I update state with axios put request on my React application? (React/Node Express) 在React with Redux中从我的商店/状态中删除项目后,如何更新视图 - How do I get my view to update after an item was removed from my store/State in React with Redux 如何使用来自 React Router 的路由参数发出 axios 请求,然后根据响应更新 state? - How do I make an axios request using a route parameter from React Router, then update state based on the response? 如果我的道具在 React 中发生变化,如何更新 state 以强制重新渲染? - How do I update the state to force a rerender if my props change in React? React:如何从外部函数更新组件状态? - React: How do I update my components state from an external function?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM