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

如何在GatsbyJS中集成Google Maps JavaScript API地图

解决Gatsby项目中Google Maps导航返回后消失的问题

这个问题我之前在Gatsby项目里踩过坑,本质是Gatsby的客户端路由机制导致的:当你首次加载页面时,html.js里的Google Maps脚本会执行,initMap回调触发初始化地图;但当你导航离开再返回时,页面不会重新加载HTML,脚本已经加载完成,callback=initMap不会再次触发,而且React组件重新渲染后,地图容器是空的,却没有重新初始化地图实例。

下面给你两种可行的解决方案,推荐第一种更符合React组件化的方案:

方案一:将地图初始化逻辑移到React组件内部(推荐)

把地图的加载、初始化和清理逻辑都封装到React组件里,利用React的生命周期钩子(useEffect)来适配Gatsby的客户端路由,这样每次组件挂载(包括导航返回时)都会重新初始化地图。

import { useEffect, useRef } from 'react';

const MapComponent = () => {
  // 存地图容器DOM元素
  const mapContainerRef = useRef(null);
  // 存地图实例,方便后续销毁
  const mapInstanceRef = useRef(null);

  useEffect(() => {
    // 定义地图初始化函数
    const initMap = () => {
      if (!mapContainerRef.current || !window.google?.maps) return;
      
      // 先销毁旧实例(如果有的话)
      if (mapInstanceRef.current) {
        mapInstanceRef.current = null;
      }

      // 创建新的地图实例
      mapInstanceRef.current = new window.google.maps.Map(mapContainerRef.current, {
        center: { lat: -34.397, lng: 150.644 },
        zoom: 8,
      });
    };

    // 检查Google Maps是否已加载
    if (window.google?.maps) {
      initMap();
    } else {
      // 动态加载Google Maps脚本
      const script = document.createElement('script');
      script.src = `https://maps.googleapis.com/maps/api/js?key=你的API密钥`;
      script.async = true;
      // 脚本加载完成后初始化地图
      script.onload = initMap;
      document.body.appendChild(script);

      // 清理函数:移除脚本
      return () => {
        document.body.removeChild(script);
      };
    }

    // 组件卸载时销毁地图实例,释放资源
    return () => {
      if (mapInstanceRef.current) {
        mapInstanceRef.current = null;
      }
    };
  }, []);

  return <div ref={mapContainerRef} style={{ width: '100%', height: '400px' }} />;
};

export default MapComponent;

为什么这个方案有效?

  • 组件每次挂载(包括导航返回)都会触发useEffect,检查地图脚本是否加载,加载了就初始化,没加载就动态加载。
  • 用useRef保存地图实例和容器,确保能准确控制地图的创建和销毁,避免内存泄漏。
  • 完全脱离html.js的全局脚本,更符合React组件化的开发模式,也更容易维护。

方案二:保留html.js脚本,手动触发初始化

如果你不想改动html.js的脚本结构,可以修改全局的initMap函数,让它支持重复调用,然后在React组件挂载时手动触发初始化。

第一步:修改html.js里的脚本

把initMap改成可以重复执行的逻辑,先检查并销毁旧地图实例:

<script dangerouslySetInnerHTML={{ __html: `
  var map;
  function initMap() {
    const mapElement = document.getElementById('map');
    if (!mapElement) return;
    
    // 销毁旧地图实例
    if (map) {
      map = null;
    }
    
    // 初始化新地图
    map = new google.maps.Map(mapElement, {
      center: {lat: -34.397, lng: 150.644},
      zoom: 8
    });
  }
` }}></script>
<script src="https://maps.googleapis.com/maps/api/js?key=你的API密钥" async defer></script>

第二步:在React组件里手动触发初始化

利用useEffect在组件挂载时,检查Google Maps是否加载完成,完成后调用initMap:

import { useEffect } from 'react';

const MapPage = () => {
  useEffect(() => {
    // 循环检查Google Maps是否加载完成
    const checkMapLoaded = () => {
      if (window.google?.maps) {
        window.initMap();
      } else {
        setTimeout(checkMapLoaded, 100);
      }
    };

    checkMapLoaded();

    // 组件卸载时销毁地图实例
    return () => {
      if (window.map) {
        window.map = null;
      }
    };
  }, []);

  return <div id="map" style={{ width: '100%', height: '400px' }} />;
};

export default MapPage;

为什么这个方案有效?

  • 导航返回时组件重新挂载,useEffect会触发checkMapLoaded,手动调用initMap重新初始化地图。
  • 修改后的initMap会先销毁旧实例,避免重复创建导致的冲突。

总结

两种方案都能解决导航返回地图消失的问题,方案一更推荐,因为它把地图逻辑完全封装在组件内部,更灵活、更易维护,也符合React的开发理念。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:45:56