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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 16:12:52