React中Google Maps多边形clickable状态无法随组件状态更新
问题
现有代码能在地图就绪时正常渲染多边形,但需要根据独立状态控制多边形是否可点击。当前将clickable设为!checkCreating()的结果时,该值仅保留初始渲染时的状态,后续组件状态变化无法更新多边形的可点击性。
checkCreating()用于检查是否正在绘制其他多边形,此时应将其余多边形设为不可点击,避免用户误触进入详情页;非绘制状态下恢复可点击。但目前多边形不会随状态变化重新检查该条件。
原代码:
useEffect(() => { if (map) { const forRetrun = [] zones.forEach((z: ICreating) => forRetrun.push({ ...z, color: getColor(1) })) sections.forEach((s: ICreating) => forRetrun.push({ ...s, color: getColor(2) })) blocks.forEach((b: ICreating) => forRetrun.push({ ...b, color: getColor(3) })) pits.forEach((p: ICreating) => forRetrun.push({ ...p, color: getColor(4) })) console.log(forRetrun) forRetrun.forEach((p) => { // Create label for polygon const center = getCenter(p) const content = document.createElement('p') content.innerText = p.areaName content.className = 'white-text' // forRetrun.push({ id: 'creating', path: creating.path, color: getColor(creating.type) }) if (loadedPolygons.current.some((lp) => lp.id == p.id + '_' + p.type)) { const foundIndex = loadedPolygons.current.findIndex((lp) => lp?.id == p.id + '_' + p.type) loadedPolygons.current[foundIndex].polygon.setMap(null) loadedPolygons.current[foundIndex].label.setMap(null) delete loadedPolygons.current[foundIndex] } loadedPolygons.current.push({ id: p.id + '_' + p.type, label: new google.maps.marker.AdvancedMarkerElement({ position: { lat: Number(center.lat), lng: Number(center.lng) }, map, content, }), polygon: new google.maps.Polygon({ paths: p.path, fillColor: p.color, map, strokeWeight: 0.5, clickable: !checkCreating(), /// <====== HERE }), }) loadedPolygons.current[loadedPolygons.current.length - 1].polygon.addListener('click', () => { handleGetInfo(p) }) }) } }, [map, zones, sections, blocks, pits])
解决方案
原因分析
问题核心在于:useEffect的依赖数组中未包含checkCreating()所依赖的状态,导致只有当map、zones等依赖变化时才会重新执行,而checkCreating()的状态改变不会触发useEffect,多边形的clickable属性也就不会更新。
优化方案
有两种可行的修改方式,按需选择:
方式1:更新依赖数组,触发多边形重建(简单直接)
将checkCreating()依赖的状态(假设为isCreating)加入useEffect的依赖数组,这样当绘制状态变化时,会重新执行useEffect,重建多边形并更新clickable属性。
修改后的useEffect依赖:
}, [map, zones, sections, blocks, pits, isCreating]) // 加入checkCreating依赖的状态
方式2:单独监听状态变化,直接更新已存在的多边形(性能更优)
不需要每次都删除重建多边形,而是新增一个useEffect专门监听绘制状态变化,遍历已加载的多边形直接调用setOptions更新clickable属性:
// 新增useEffect监听绘制状态变化,更新所有多边形的可点击性 useEffect(() => { if (map && loadedPolygons.current.length > 0) { const isClickable = !checkCreating(); loadedPolygons.current.forEach(item => { item.polygon.setOptions({ clickable: isClickable }); }); } }, [map, isCreating]); // 这里加入checkCreating依赖的状态
同时保留原有的useEffect负责多边形的初始化和数据更新,这样既保证了数据变化时的正确渲染,又能在绘制状态变化时高效更新可点击性。
注意事项
- 确保
checkCreating()依赖的状态(比如isCreating)是组件的响应式状态(如useState声明的变量),这样才能被useEffect正确监听。 - 方式2相比方式1性能更好,避免了频繁删除重建DOM元素和地图对象。
内容的提问来源于stack exchange,提问作者Brimstone
相关产品推荐
相关产品推荐

