JS创建新对象返回空值,calculateDistance执行后setState无法更新状态
问题解决方案
核心原因
你的代码无法拿到预期结果本质是异步时序问题:Leaflet 的 routesfound 是路由计算完成后才会触发的异步事件,你在 calculateDistance 中同步返回数组时,所有回调都还没执行,拿到的全是空对象。
其他隐藏问题
- 每次调用
calculateDistance都重新初始化地图实例,多次调用会抛出 DOM 已被占用的错误,地图实例只需在组件挂载时初始化一次即可。 - 你用
Object.defineProperty新增的属性默认是不可枚举的,JSON.stringify序列化时会自动忽略,这就是你之前给原对象加属性、序列化后看不到变化的原因。
改造代码
1. 提前初始化地图
在组件挂载阶段完成地图初始化,存在实例属性上复用:
componentDidMount() { this.map = L.map('route-map').setView([52.237049, 21.017532], 11); // 其他地图初始化逻辑写在这里 }
2. 改造异步计算逻辑
把 calculateDistance 改造成返回 Promise,等所有路由计算完成后再返回结果:
calculateDistance(result) { // 用Promise.all等待所有异步路由计算完成 return Promise.all(this.state.teams.map(team => { return new Promise((resolve) => { const routeControl = L.Routing.control({ waypoints: [ L.latLng(team.lat, team.long), L.latLng(result.y, result.x) ], show: true, }).addTo(this.map) routeControl.on('routesfound', e => { const dist = e.routes[0].summary.totalDistance; // 直接返回普通对象,需要保留原team属性直接展开即可 resolve({ ...team, id: team.id, distance: dist }) // 移除用完的控件,避免地图上堆多余元素 this.map.removeControl(routeControl) }) }) })) }
3. 改造事件处理逻辑
等待异步计算完成后再更新 state:
async handleSearch(result) { const newTeams = await this.calculateDistance(result) this.setState({ teams: newTeams }) }
补充说明
如果你确实需要用 Object.defineProperty 定义不可写的属性,必须加上 enumerable: true 配置,否则序列化时会被忽略:
Object.defineProperty(newTeam, 'distance', { value: dist, writable: false, enumerable: true // 必加配置项 })
内容的提问来源于stack exchange,提问作者JujV
相关产品推荐
相关产品推荐

