Next.js使用PrimeReact GMap集成Google Maps报google未定义如何解决
错误根因
ReferenceError: google is not defined 报错由两个核心问题共同导致:
- PrimeReact GMap 组件强依赖浏览器全局
google对象,该对象仅在Google Maps JavaScript SDK加载完成后才会注入,官方示例默认省略了SDK加载的前置步骤 - Next.js 默认开启服务端渲染,服务端执行环境无浏览器全局API,且GMap为纯客户端组件,直接静态导入并在服务端执行渲染逻辑会直接触发引用错误
修复步骤
1. 配置客户端渲染
禁止GMap组件在服务端运行,根据你使用的Next.js路由模式做对应配置:
- App Router 项目:在组件文件顶部添加
'use client'指令 - Pages Router / App Router 通用:使用Next.js内置的
dynamic方法动态导入GMap组件,关闭SSR:
import dynamic from 'next/dynamic'; // 动态导入GMap,关闭服务端渲染,配置加载占位 const GMap = dynamic( () => import('primereact/gmap').then(module => module.GMap), { ssr: false, loading: () => <div style={{minHeight: '320px'}}>地图加载中...</div> } );
2. 预加载Google Maps SDK
在客户端侧手动加载SDK,等待SDK加载完成、全局google对象注入后再渲染GMap组件,可通过自定义Hook实现加载逻辑:
import { useState, useEffect } from 'react'; const useGoogleMapsLoader = (apiKey) => { const [isLoaded, setIsLoaded] = useState(false); useEffect(() => { // 已加载过直接返回 if (window.google?.maps) { setIsLoaded(true); return; } // 创建脚本标签注入SDK const script = document.createElement('script'); script.src = `https://maps.googleapis.com/maps/api/js?key=${apiKey}`; script.async = true; script.defer = true; script.onload = () => setIsLoaded(true); document.body.appendChild(script); return () => { // 组件卸载时移除脚本,避免重复注入 if (document.body.contains(script)) { document.body.removeChild(script); } } }, [apiKey]); return isLoaded; }
注意:需要提前申请Google Maps服务的API密钥,同时在对应云服务控制台开通Maps JavaScript API权限、配置生产域名白名单,避免密钥被滥用。
3. 增加渲染判断逻辑
在组件中结合SDK加载状态控制GMap的渲染时机,完整可用代码如下:
'use client'; // App Router 项目保留此行,Pages Router可删除 import { useState, useEffect } from 'react'; import dynamic from 'next/dynamic'; const GMap = dynamic( () => import('primereact/gmap').then(module => module.GMap), { ssr: false, loading: () => <div style={{width: '100%', minHeight: '320px'}}>地图加载中...</div> } ); const useGoogleMapsLoader = (apiKey) => { const [isLoaded, setIsLoaded] = useState(false); useEffect(() => { if (window.google?.maps) { setIsLoaded(true); return; } const script = document.createElement('script'); script.src = `https://maps.googleapis.com/maps/api/js?key=${apiKey}`; script.async = true; script.defer = true; script.onload = () => setIsLoaded(true); document.body.appendChild(script); return () => { if (document.body.contains(script)) { document.body.removeChild(script); } } }, [apiKey]); return isLoaded; } const DealershipLocation = () => { // 替换为你自己的Google Maps API密钥 const isMapLoaded = useGoogleMapsLoader('YOUR_GOOGLE_MAPS_API_KEY'); const options = { center: {lat: 36.890257, lng: 30.707417}, zoom: 12 }; return ( <div> {isMapLoaded ? ( <GMap options={options} style={{width: '100%', minHeight: '320px'}} /> ) : ( <div style={{width: '100%', minHeight: '320px'}}>地图资源加载中...</div> )} </div> ) } export default DealershipLocation
常见排查点
- 如果SDK加载后仍然报错,检查API密钥是否有效、是否开通了对应API权限,浏览器控制台是否有SDK加载相关的403/401错误
- 如果页面存在多实例GMap的场景,调整脚本加载逻辑,避免重复注入SDK脚本
- PrimeReact版本需和React、Next.js版本匹配,版本不兼容也可能导致组件渲染异常
内容的提问来源于stack exchange,提问作者julBayonna
相关产品推荐
相关产品推荐

