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

HOC中Google Maps Geocode回调内执行this.setState的方法

解决Google Maps Geocode回调中无法调用this.setState的问题

这个问题的核心原因是普通回调函数里的this指向和React组件实例的this不一致。geocoder.geocode的第二个参数是普通函数,当它被执行时,this的上下文已经不是你的组件实例了,自然无法调用this.setState。

下面给你三种可行的解决方案,按推荐程度排序:

方案1:使用箭头函数作为回调(最简洁,推荐)

箭头函数不会绑定自己的this,它会继承外层作用域的this,也就是你的组件实例。修改代码如下:

onMarkerPositionChanged: (e, reloadList, marker) => {
  const geocoder = new window.google.maps.Geocoder();
  const myLatlng = new window.google.maps.LatLng(e.latLng.lat(), e.latLng.lng());
  let dragEndPositions;
  let nextMarkers;
  let sitiosNew = [];
  sessionStorage.id = marker.id;

  // 把普通回调改成箭头函数,继承外层组件的this
  geocoder.geocode({'latLng': myLatlng }, (results, status) => {
    if (status == window.google.maps.GeocoderStatus.OK) {
      if (results[0]) {
        dragEndPositions = results[0].formatted_address;
        console.log(dragEndPositions);
        
        nextMarkers = [{
          position: myLatlng,
          nombre: dragEndPositions,
          icon: icon,
          direccion: dragEndPositions,
          latitud: e.latLng.lat(),
          longitud: e.latLng.lng(),
          id: sessionStorage.id
        }];

        if(sessionStorage.auto){
          JSON.parse(sessionStorage.auto).forEach(nextMarker => {
            // 修正:nextMarkers是数组,需取第一个元素的id
            if (nextMarker.id === nextMarkers[0].id) {
              sitiosNew.push(nextMarkers[0]);
            } else {
              sitiosNew.push(nextMarker);
            }
          });
        } else {
          // 没有缓存时直接添加当前标记
          sitiosNew.push(nextMarkers[0]);
        }

        if(sessionStorage.auto){
          sessionStorage.removeItem("auto");
        }
        sessionStorage.auto = JSON.stringify(sitiosNew);
        
        // 现在this指向组件实例,可正常调用setState
        this.setState({ markers: sitiosNew }, () => {
          // 可选:把reloadList放在setState回调里,确保状态更新完成后执行
          reloadList();
        });
      }
    }
  });
}

方案2:提前保存组件的this引用

在回调外部把组件的this保存到一个变量(比如that),然后在回调里使用这个变量:

onMarkerPositionChanged: (e, reloadList, marker) => {
  const geocoder = new window.google.maps.Geocoder();
  const myLatlng = new window.google.maps.LatLng(e.latLng.lat(), e.latLng.lng());
  let dragEndPositions;
  let nextMarkers;
  let sitiosNew = [];
  sessionStorage.id = marker.id;
  // 保存组件的this引用
  const that = this;

  geocoder.geocode({'latLng': myLatlng }, function(results, status) {
    if (status == window.google.maps.GeocoderStatus.OK) {
      if (results[0]) {
        // ... 中间逻辑同方案1 ...
        
        // 使用that代替this调用setState
        that.setState({ markers: sitiosNew }, reloadList);
      }
    }
  });
}

方案3:使用bind绑定this到回调函数

通过Function.prototype.bind把回调函数的this强制绑定到组件实例:

onMarkerPositionChanged: (e, reloadList, marker) => {
  const geocoder = new window.google.maps.Geocoder();
  const myLatlng = new window.google.maps.LatLng(e.latLng.lat(), e.latLng.lng());
  let dragEndPositions;
  let nextMarkers;
  let sitiosNew = [];
  sessionStorage.id = marker.id;

  // 使用bind绑定组件的this到回调函数
  geocoder.geocode({'latLng': myLatlng }, function(results, status) {
    if (status == window.google.maps.GeocoderStatus.OK) {
      if (results[0]) {
        // ... 中间逻辑同方案1 ...
        
        this.setState({ markers: sitiosNew }, reloadList);
      }
    }
  }.bind(this)); // 绑定组件实例的this
}

额外注意点

  1. 原代码里的小问题:nextMarkers是数组,不能直接用nextMarkers.id,需要取nextMarkers[0].id,我在方案1中已经修正。
  2. this.setState是异步操作,如果reloadList依赖新的状态,最好把它放在setState的第二个回调参数里,确保状态更新完成后再执行。

内容的提问来源于stack exchange,提问作者Erick Vivanco

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:35:46