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

如何避免React中Fusion Maps地图因状态变量变更重渲染

解决React中FusionMaps悬停时地图闪烁的问题

我用React结合FusionMaps做了美国地图,现在碰到个糟心的问题:鼠标悬停到某个州的时候,地图会不停闪烁,体验特别差。查了下原因,是我给地图绑了entityRollover事件,事件里会更新hoveredState这个状态变量,导致整个组件(包括地图)跟着重渲染。我想要的效果是,悬停时只在旁边的文本框里显示州名,地图本身别跟着瞎动。知道useRef、useMemo、useCallback这些Hook能解决,但不会具体用。

两种解决办法

办法一:用useRef直接改DOM(最简单)

不用状态变量,直接用useRef拿到文本框的DOM元素,在悬停事件里直接修改它的内容,这样不会触发任何组件重渲染,自然就不会闪烁了。

代码示例:

import { useRef } from 'react';
import ReactFusioncharts from 'react-fusioncharts';
import FusionCharts from 'fusioncharts';
import Maps from 'fusionmaps';
import USA from 'fusioncharts/maps/fusioncharts.usa';

FusionCharts.addDep(Maps);
FusionCharts.addDep(USA);

function App() {
  // 存储文本框的DOM引用
  const stateNameRef = useRef(null);

  const chartConfigs = {
    type: 'usa',
    width: '100%',
    height: '500',
    dataFormat: 'json',
    dataSource: {
      "chart": {
        "caption": "美国人口分布",
        "subcaption": "2019年估算值",
        "numbersuffix": "百万",
        "entityFillHoverColor": "#FFF9C4",
        "theme": "fusion"
      },
      "data": [
        // 这里放入你原代码中的地图数据即可
      ]
    },
    events: {
      entityRollover: (event, data) => {
        // 直接更新文本框内容
        if (stateNameRef.current) {
          stateNameRef.current.textContent = data.label;
        }
      },
      entityRollout: () => {
        // 鼠标移开时清空文本框
        if (stateNameRef.current) {
          stateNameRef.current.textContent = '';
        }
      }
    }
  };

  return (
    <div>
      <div ref={stateNameRef} style={{ fontSize: '24px', marginBottom: '20px' }}></div>
      <ReactFusioncharts {...chartConfigs} />
    </div>
  );
}

export default App;

办法二:拆分组件+用useMemo缓存地图

如果必须用状态管理(比如之后还要用到hoveredState做其他逻辑),可以把地图拆成独立的子组件,用useMemo缓存它,让它只在地图配置变化时才重渲染,不受父组件的hoveredState影响。

代码示例:

import { useState, useMemo, useCallback } from 'react';
import ReactFusioncharts from 'react-fusioncharts';
import FusionCharts from 'fusioncharts';
import Maps from 'fusionmaps';
import USA from 'fusioncharts/maps/fusioncharts.usa';

FusionCharts.addDep(Maps);
FusionCharts.addDep(USA);

// 独立的地图子组件
const USMap = ({ onStateHover }) => {
  const chartConfigs = {
    type: 'usa',
    width: '100%',
    height: '500',
    dataFormat: 'json',
    dataSource: {
      "chart": {
        "caption": "美国人口分布",
        "subcaption": "2019年估算值",
        "numbersuffix": "百万",
        "entityFillHoverColor": "#FFF9C4",
        "theme": "fusion"
      },
      "data": [
        // 原地图数据放入此处
      ]
    },
    events: {
      entityRollover: (event, data) => onStateHover(data.label),
      entityRollout: () => onStateHover('')
    }
  };

  return <ReactFusioncharts {...chartConfigs} />;
};

function App() {
  const [hoveredState, setHoveredState] = useState('');

  // 用useCallback保证回调函数引用稳定
  const handleStateHover = useCallback((state) => {
    setHoveredState(state);
  }, []);

  // 用useMemo缓存地图组件,仅当handleStateHover变化时重新生成
  const cachedMap = useMemo(() => {
    return <USMap onStateHover={handleStateHover} />;
  }, [handleStateHover]);

  return (
    <div>
      <div style={{ fontSize: '24px', marginBottom: '20px' }}>{hoveredState}</div>
      {cachedMap}
    </div>
  );
}

export default App;

问题复现步骤

  • 创建React项目:
npx create-react-app map-demo
  • 安装依赖包:
npm i fusioncharts react-fusioncharts fusionmaps
  • 将上述代码替换到src/App.js中,补充好原代码中的地图数据即可复现原问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 08:15:47