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

React函数组件State无法在组件函数中获取问题求助

问题原因分析

你遇到的问题核心是函数闭包的快照特性,以及Google Maps脚本回调机制导致的旧函数引用问题:

  • 组件首次渲染时,initMap函数被创建,此时它捕获的polygons是初始的空数组。
  • 你把initMap挂载到了window对象上,Google Maps脚本加载完成后调用的是这个首次渲染时创建的旧函数,它永远只能访问到初始的空polygons。
  • 而useEffect依赖polygons,每次polygons更新都会重新执行,此时它访问的是当前渲染周期的最新polygons状态,所以日志能正确输出。
解决方案

核心思路是避免依赖window上的旧函数引用,改用React的ref保存地图实例,将地图初始化与多边形更新分离,只在必要时更新多边形:

修复后的完整代码

import { useState, useEffect, useRef } from "react";
import Helmet from "react-helmet";

function MyMap(props) {
  const [polygons, setPolygons] = useState([]);
  const mapRef = useRef(null); // 保存地图实例
  const polygonRefs = useRef([]); // 保存已绘制的多边形实例,用于清理

  // 初始化地图,只执行一次
  useEffect(() => {
    if (!window.google || mapRef.current) return;

    const { zoom, center } = props.props;
    const mapInstance = new window.google.maps.Map(
      document.getElementById("google-map"),
      {
        center: center,
        zoom: zoom,
        mapTypeId: window.google.maps.MapTypeId.ROADMAP,
        zoomControl: false,
      }
    );
    mapRef.current = mapInstance;
  }, []);

  // 监听polygons变化,更新多边形
  useEffect(() => {
    if (!mapRef.current) return;

    // 先清理旧的多边形
    polygonRefs.current.forEach(polygon => polygon.setMap(null));
    polygonRefs.current = [];

    // 绘制新的多边形
    if (polygons?.length) {
      const newPolygons = polygons.map(polygonData => {
        const polygon = new window.google.maps.Polygon({
          paths: polygonData,
          strokeColor: "#FF0000",
          map: mapRef.current,
        });
        return polygon;
      });
      polygonRefs.current = newPolygons;
    }
  }, [polygons]);

  const mapElement = (
    <div
      className="map-container"
      id="google-map"
      style={{ width: "100%", height: "100%" }}
    />
  );

  return (
    <section className="map-wrapper-container">
      {mapElement}
      <Helmet>
        <script
          type="text/javascript"
          async={true}
          defer={true}
          src={`https://maps.googleapis.com/maps/api/js?key=<APIKEY>`}
        />
      </Helmet>
    </section>
  );
}
export default MyMap;

关键修复点

  • 移除window.initMap绑定:不再依赖Google Maps脚本的callback参数,而是在React的useEffect中等待Google Maps加载完成后初始化地图。
  • 用useRef保存地图实例:确保后续更新多边形时能访问到同一个地图对象,避免重复创建地图。
  • 分离地图初始化与多边形更新:地图只初始化一次,polygons变化时仅更新多边形,提升性能。
  • 清理旧多边形:用polygonRefs保存已绘制的多边形实例,更新时先移除旧的,避免地图上残留旧图形。
  • 避免闭包陷阱:通过useRef访问最新的地图和多边形实例,而不是依赖函数闭包中的状态快照。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 04:43:14