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

React集成AmCharts地图:API数据加载顺序问题求助

搞定这个异步数据和地图初始化的问题很简单,核心就是让地图等数据到位了再渲染~我给你两种方案,分别对应函数组件和类组件,都不用localStorage,直接用React状态管理数据:

方案一:函数组件(推荐,React 16.8+)

利用useState存储API数据,useEffect里先异步获取数据,拿到数据后再初始化地图:

import React, { useState, useEffect, useRef } from 'react';
import * as am4core from "@amcharts/amcharts4/core";
import * as am4maps from "@amcharts/amcharts4/maps";
import am4geodata_worldLow from "@amcharts/amcharts4-geodata/worldLow";

const WorldMap = () => {
  // 用状态存储API返回的地理数据
  const [geoData, setGeoData] = useState(null);
  // 存储地图实例,方便组件卸载时销毁
  const mapRef = useRef(null);

  // 你的API请求函数,替换成实际的getGeography
  const getGeography = async () => {
    try {
      // 这里替换成你的真实API地址
      const response = await fetch('https://your-api-url.com/geo-data');
      const data = await response.json();
      return data;
    } catch (error) {
      console.error('获取地理数据失败:', error);
      return null;
    }
  };

  useEffect(() => {
    // 异步初始化流程:先拿数据,再初始化地图
    const initMap = async () => {
      const data = await getGeography();
      if (!data) return;
      setGeoData(data);

      // 初始化AmCharts地图
      let chart = am4core.create("mapdiv", am4maps.MapChart);
      chart.geodata = am4geodata_worldLow;
      chart.projection = new am4maps.projections.Miller();

      // 创建地图系列
      let polygonSeries = chart.series.push(new am4maps.MapPolygonSeries());
      polygonSeries.useGeodata = true;

      // 转换数据格式:AmCharts的国家代码是大写,印度对应代码是IN(不是INDIA)
      polygonSeries.data = Object.entries(data).map(([code, value]) => {
        let mapCode = code.toUpperCase();
        if (code === 'india') mapCode = 'IN';
        return { id: mapCode, value };
      });

      // 设置颜色规则
      let colorAxis = chart.createChild(am4core.ColorAxis);
      colorAxis.dataFields.value = "value";
      colorAxis.renderer.labels.template.disabled = true;
      colorAxis.renderer.minWidth = 0;

      // 地图基础样式
      polygonSeries.mapPolygons.template.fill = am4core.color("#eee");
      polygonSeries.mapPolygons.template.stroke = am4core.color("#fff");
      polygonSeries.mapPolygons.template.strokeWidth = 0.5;
      polygonSeries.mapPolygons.template.cursorOverStyle = am4core.MouseCursorStyle.pointer;

      // 存储地图实例到ref
      mapRef.current = chart;
    };

    initMap();

    // 组件卸载时销毁地图,避免内存泄漏
    return () => {
      if (mapRef.current) {
        mapRef.current.dispose();
      }
    };
  }, []);

  return (
    <div>
      {/* 数据未加载时显示提示 */}
      {!geoData ? (
        <div>加载地图数据中...</div>
      ) : (
        <div id="mapdiv" style={{ width: "100%", height: "500px" }}></div>
      )}
    </div>
  );
};

export default WorldMap;

方案二:类组件

如果你的项目还在用类组件,可以这样写:

import React from 'react';
import * as am4core from "@amcharts/amcharts4/core";
import * as am4maps from "@amcharts/amcharts4/maps";
import am4geodata_worldLow from "@amcharts/amcharts4-geodata/worldLow";

class WorldMap extends React.Component {
  state = {
    geoData: null
  };
  mapInstance = null;

  getGeography = async () => {
    try {
      const response = await fetch('https://your-api-url.com/geo-data');
      const data = await response.json();
      return data;
    } catch (error) {
      console.error('获取地理数据失败:', error);
      return null;
    }
  };

  initMap = (data) => {
    let chart = am4core.create("mapdiv", am4maps.MapChart);
    chart.geodata = am4geodata_worldLow;
    chart.projection = new am4maps.projections.Miller();

    let polygonSeries = chart.series.push(new am4maps.MapPolygonSeries());
    polygonSeries.useGeodata = true;

    polygonSeries.data = Object.entries(data).map(([code, value]) => {
      let mapCode = code.toUpperCase();
      if (code === 'india') mapCode = 'IN';
      return { id: mapCode, value };
    });

    let colorAxis = chart.createChild(am4core.ColorAxis);
    colorAxis.dataFields.value = "value";
    colorAxis.renderer.labels.template.disabled = true;
    colorAxis.renderer.minWidth = 0;

    polygonSeries.mapPolygons.template.fill = am4core.color("#eee");
    polygonSeries.mapPolygons.template.stroke = am4core.color("#fff");
    polygonSeries.mapPolygons.template.strokeWidth = 0.5;
    polygonSeries.mapPolygons.template.cursorOverStyle = am4core.MouseCursorStyle.pointer;

    this.mapInstance = chart;
  };

  async componentDidMount() {
    const data = await this.getGeography();
    if (data) {
      // 数据获取成功后更新状态,再初始化地图
      this.setState({ geoData: data }, () => {
        this.initMap(data);
      });
    }
  }

  componentWillUnmount() {
    // 组件销毁时清理地图实例
    if (this.mapInstance) {
      this.mapInstance.dispose();
    }
  }

  render() {
    const { geoData } = this.state;
    return (
      <div>
        {!geoData ? (
          <div>加载地图数据中...</div>
        ) : (
          <div id="mapdiv" style={{ width: "100%", height: "500px" }}></div>
        )}
      </div>
    );
  }
}

export default WorldMap;

关键注意点:

  • 数据格式转换:AmCharts的国家代码是大写标准代码,比如印度是IN而不是INDIA,所以要做对应转换
  • 异步顺序:用async/await确保API数据返回后再执行地图初始化逻辑
  • 内存泄漏处理:组件卸载时一定要销毁AmCharts实例,避免内存泄漏
  • 加载状态:数据未返回时显示加载提示,提升用户体验

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 07:30:50