热力图数据更新后为什么不重新渲染?

玉泽 阅读 6

我在用 React + 高德地图 SDK 做一个热力图功能,初始加载时能正常显示,但当我通过接口获取新数据并 setState 后,热力图却没更新。我确认数据格式是对的,也调用了 setHeatmapData 方法,但地图上还是旧的热力图。

是不是我漏掉了什么刷新机制?或者高德的 Heatmap 实例需要手动 destroy 再重建?试过 forceUpdate 也没用……

useEffect(() => {
  if (map && heatmapData.length > 0) {
    const heatmap = new AMap.Heatmap(map, {
      radius: 20,
      opacity: [0.6, 0.9],
    });
    heatmap.setDataSet({
      data: heatmapData,
      max: 100,
    });
  }
}, [map, heatmapData]);
我来解答 赞 0 收藏
二维码
手机扫码查看
1 条解答
 ___伊可
你的问题在于每次 useEffect 执行时都在创建新的 Heatmap 实例,但没有管理好实例的生命周期。高德地图的 Heatmap 对象不会自动销毁重建,你需要在数据更新时正确处理。

问题的根本原因是这样的:第一次渲染时创建了 heatmap 实例并绑定了数据,之后数据变化触发 useEffect 重新执行,你又创建了一个新的实例,但这个新实例并没有替换掉地图上原来的那个,地图上显示的还是第一个实例的数据。

来解决这个问题:

第一步,用 useRef 保存 heatmap 实例的引用,这样我们才能在后续更新时访问到它。

第二步,在创建新实例前先判断是否已存在,如果存在就先调用 destroy 方法销毁,然后再创建新的。

第三步,把 heatmap 实例也放入 useEffect 的依赖数组里,确保每次数据更新都能正确处理。

完整代码如下:

import { useEffect, useRef } from 'react';

function HeatmapComponent({ map, heatmapData }) {
// 用 ref 保存 heatmap 实例
const heatmapInstance = useRef(null);

useEffect(() => {
// 条件检查,map 和数据都要有才继续
if (!map || !heatmapData || heatmapData.length === 0) {
return;
}

// 如果已经存在 heatmap 实例,先销毁
if (heatmapInstance.current) {
heatmapInstance.current.setDataSet({
data: heatmapData,
max: 100,
});
// 这里其实可以直接更新数据,不需要重建
return;
}

// 首次创建实例
const heatmap = new AMap.Heatmap(map, {
radius: 20,
opacity: [0.6, 0.9],
});

heatmap.setDataSet({
data: heatmapData,
max: 100,
});

// 保存实例引用
heatmapInstance.current = heatmap;
}, [map, heatmapData]);

// 可选:如果组件卸载,清理实例
useEffect(() => {
return () => {
if (heatmapInstance.current) {
heatmapInstance.current.setDataSet({ data: [], max: 0 });
heatmapInstance.current = null;
}
};
}, []);

return null;
}


这里有个关键点我解释一下:其实更新热力图数据不需要每次都销毁重建,高德的 Heatmap 提供了 setDataSet 方法,直接调用这个方法传入新数据就能更新。你只需要在第一次时创建实例,之后数据变化只用 setDataSet 更新数据就行,这样性能也会更好。

如果你确实需要完全重建(比如配置项也需要变),那就在创建新实例前调用 destroy 方法:

if (heatmapInstance.current) {
heatmapInstance.current.destroy();
heatmapInstance.current = null;
}


还有一个可能的坑:AMap.Heatmap 可能需要你手动引入插件。在创建 Heatmap 实例前,确保已经加载了 Heatmap 插件:

// 在地图初始化时加载插件
map = new AMap.Map('container', {
// 配置项
});

// 加载热力图插件
AMap.plugin('AMap.Heatmap', function() {
// 在回调里才能创建 Heatmap 实例
});


你可以检查一下是否有加载这个插件,如果没加载,热力图也不会显示。

总结一下:核心问题就是没有保存实例引用,导致每次数据更新都创建新实例但没有正确替换。解决方案就是用 ref 保存实例,然后判断是首次创建还是更新数据。
点赞
2026-03-18 16:10