如何在react-google-maps的DirectionsService外部使用routes变量?
解决React-google-maps中DirectionsService结果无法在外部使用的问题
嘿,这个问题我太熟悉了!你遇到的核心问题是DirectionsService.route是异步操作,再加上用全局变量管理状态不符合React的设计思路,所以才会出现外部拿不到值的情况。咱们一步步来解决:
为什么全局变量不行?
DirectionsService.route是异步的,它的回调函数会在API请求完成后才执行。你写的外部console.log("undefined: ", routes)是同步代码,会先于回调执行,这时候routes还没被赋值,自然是undefined。而且全局变量在React组件里很容易导致状态混乱,完全不推荐用。
正确的解决方案:用组件State管理路由信息
React组件的state是用来管理组件内部动态状态的,异步操作的结果应该存在state里,这样当状态更新时,组件会自动重新渲染,你就能在render里拿到最新的值了。
修改步骤:
- 初始化组件State:在constructor里定义需要的状态,包括路由信息
routeInfo - 在异步回调中更新State:把DirectionsService返回的路由信息存入state,而不是全局变量
- 优化组件结构:不要在render里定义
DirectionsComponent,避免重复创建组件 - 在render中使用State的值:通过
this.state.routeInfo获取数据,记得做空值判断
修改后的完整代码:
/*global google*/ import React from 'react' import { compose, withProps, lifecycle } from 'recompose' import {withScriptjs, withGoogleMap, GoogleMap, DirectionsRenderer} from 'react-google-maps' // 把DirectionsComponent提到组件外面,避免每次render重新创建 const DirectionsComponent = compose( withProps({ googleMapURL: "https://maps.googleapis.com/maps/api/js?key=AIzaSyDSMDeXXQxaeLJ4ZGXuwSKAM3NHBP4ckTc", loadingElement: <div style={{ height: `400px` }} />, containerElement: <div style={{ width: `100%` }} />, mapElement: <div style={{height: `500px`, width: `500px` }} />, }), withScriptjs, withGoogleMap, lifecycle({ componentDidMount() { const DirectionsService = new google.maps.DirectionsService(); // 从props里获取起点终点,不要用全局变量 const { origin1, origin2, destination1, destination2 } = this.props; DirectionsService.route({ origin: new google.maps.LatLng(destination1, destination2), destination: new google.maps.LatLng(origin1, origin2), travelMode: google.maps.TravelMode.DRIVING, }, (result, status) => { if (status === google.maps.DirectionsStatus.OK) { const routeInfo = result.routes[0].legs[0]; // 把路由信息和directions通过回调传给父组件 this.props.onRouteLoaded({ directions: result, markers: true, routeInfo }); } else { console.error(`error fetching directions ${result}`); } }); } }) )(props => ( <GoogleMap defaultZoom={3} > {props.directions && <DirectionsRenderer directions={props.directions} suppressMarkers={props.markers} />} </GoogleMap> )); class MyMapComponent extends React.Component { constructor(props){ super(props); // 初始化组件state this.state = { directions: null, markers: false, routeInfo: null }; } // 处理路由加载完成的回调 handleRouteLoaded = (routeData) => { this.setState(routeData); console.log("路由信息已存入state:", this.state.routeInfo); } render() { return ( <div> {/* 把state和回调传给DirectionsComponent */} <DirectionsComponent {...this.props} directions={this.state.directions} markers={this.state.markers} onRouteLoaded={this.handleRouteLoaded} /> {/* 用state里的routeInfo,做空值判断避免报错 */} {this.state.routeInfo && ( <div> <p>距离:{this.state.routeInfo.distance.text}</p> <p>预计时间:{this.state.routeInfo.duration.text}</p> </div> )} </div> ) } } export default MyMapComponent
关键改动说明:
- 把
DirectionsComponent移到了组件外部,避免每次render都重新创建,提升性能 - 通过
onRouteLoaded回调把异步获取的路由信息传递给父组件的state - 在render里通过
this.state.routeInfo访问数据,并且加了&&判断,防止数据未加载时出现Cannot read property 'distance' of null的错误 - 去掉了所有全局变量,改用props和state来传递和管理数据,符合React的状态管理规范
这样调整后,当DirectionsService的请求完成,路由信息存入state,组件会自动重新渲染,你就能在页面上看到距离信息啦!
内容的提问来源于stack exchange,提问作者hackrack
相关产品推荐
相关产品推荐

