You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:46:09