React Google Maps:在MapWithADirectionsRenderer组件中更新标记渲染
解决拖动路线后标记不更新的问题
我来帮你搞定这个问题~你现在遇到的核心问题是:markers是一个普通的外部变量,不是组件的state或者props,所以哪怕你更新了这个数组,React也不会触发组件重新渲染,自然标记就不会跟着变。
要解决这个问题,我们需要把markers改成组件的状态,让React能追踪它的变化,具体步骤如下:
步骤1:将markers转为组件state
在lifecycle的初始化阶段,把markers加到组件的state里:
lifecycle({ state: { directions: null, markers: [] // 把markers放到state中 }, // ... 其他生命周期函数 })
步骤2:更新componentDidMount中的标记生成逻辑
原来你是直接修改外部的markers数组,现在要改成用setState更新state里的markers:
componentDidMount() { const DirectionsService = new google.maps.DirectionsService(); DirectionsService.route({ origin: this.props.origin, destination: this.props.destination, travelMode: google.maps.TravelMode.DRIVING, }, (result, status) => { if (status === google.maps.DirectionsStatus.OK) { // 生成标记数组(这里按你原来的逻辑生成即可) const newMarkers = result.routes[0].legs[0].steps.map(step => ({ lat: step.start_location.lat(), lng: step.start_location.lng() })); // 同时更新directions和markers的state this.setState({ directions: result, markers: newMarkers }); } else { console.error(`error fetching directions ${result}`); } }); }
步骤3:完善onDirectionsChanged的getDirections函数
当拖动路线触发onDirectionsChanged时,需要从directionsRef中获取更新后的路线,重新生成标记并更新state:
// 把getDirections放到lifecycle里,确保能访问组件的this getDirections: function() { if (directionsRef) { const updatedDirections = directionsRef.getDirections(); // 重新生成标记数组 const newMarkers = updatedDirections.routes[0].legs[0].steps.map(step => ({ lat: step.start_location.lat(), lng: step.start_location.lng() })); // 更新state,触发组件重新渲染 this.setState({ directions: updatedDirections, markers: newMarkers }); } }
步骤4:修改渲染部分的标记引用
原来的markers.map要改成引用props传递过来的markers(因为lifecycle会把state映射到props):
props => ( <GoogleMap defaultZoom={3} defaultCenter={/* 填入你的默认坐标 */}> {props.directions && ( <DirectionsRenderer options={{draggable:true}} directions={props.directions} ref={(r) => directionsRef = r} onDirectionsChanged={props.getDirections} /> )} {/* 这里改成props.markers */} {props.markers.map((marker,i) => ( <Marker key={i} position={{ lat: marker.lat, lng: marker.lng }} /> ))} </GoogleMap> )
完整修改后的代码
let directionsRef; // 保留路线引用 const MapWithADirectionsRenderer = compose( withProps({ googleMapURL: "https://maps.googleapis.com/maps/api/js?...", loadingElement: <div style={{ height: `100%` }} />, containerElement: <div style={{ height: `100%` }} />, mapElement: <div style={{ height: `100%` }}/> }), withScriptjs, withGoogleMap, lifecycle({ state: { directions: null, markers: [] }, componentDidMount() { const DirectionsService = new google.maps.DirectionsService(); DirectionsService.route({ origin: this.props.origin, destination: this.props.destination, travelMode: google.maps.TravelMode.DRIVING, }, (result, status) => { if (status === google.maps.DirectionsStatus.OK) { const newMarkers = result.routes[0].legs[0].steps.map(step => ({ lat: step.start_location.lat(), lng: step.start_location.lng() })); this.setState({ directions: result, markers: newMarkers }); } else { console.error(`error fetching directions ${result}`); } }); }, getDirections: function() { if (directionsRef) { const updatedDirections = directionsRef.getDirections(); const newMarkers = updatedDirections.routes[0].legs[0].steps.map(step => ({ lat: step.start_location.lat(), lng: step.start_location.lng() })); this.setState({ directions: updatedDirections, markers: newMarkers }); } } }) )(props => ( <GoogleMap defaultZoom={3} defaultCenter={/* 填入你的默认坐标 */}> {props.directions && ( <DirectionsRenderer options={{draggable:true}} directions={props.directions} ref={(r) => directionsRef = r} onDirectionsChanged={props.getDirections} /> )} {props.markers.map((marker,i) => ( <Marker key={i} position={{ lat: marker.lat, lng: marker.lng }} /> ))} </GoogleMap> ));
关键说明
- React组件只有在
state或props变化时才会重新渲染,所以把markers放到state里是核心解决点。 - 在
onDirectionsChanged事件中,我们通过directionsRef.getDirections()获取更新后的路线数据,重新生成标记数组,再用setState更新,这样组件就会重新渲染标记了。 - 注意
getDirections函数的作用域,把它放到lifecycle的方法里能确保它访问到组件的this,避免作用域问题。
内容的提问来源于stack exchange,提问作者batt
相关产品推荐
相关产品推荐

