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
相关产品推荐
相关产品推荐

