如何立即更新我的 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})
})
}
我创建的用于更新状态的功能无法完美运行。
我对我修改的当前状态进行了深度复制,然后将状态设置为更改后的副本。我决定在副本上 运行 一个简单的映射并在数组中的每个对象上更新一个 属性,这使应用程序立即更新状态并显示更改。 (下面的代码中没有显示,我刚试过)
但它不适用于我真正想对副本进行的修改。由于 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})
})
}