Next.js 14.1.0集成Leaflet自定义Hook时window未定义错误修复方案
修复Next.js 14.1.0中Leaflet集成的
ReferenceError: window is not defined错误 问题原因
Leaflet是浏览器端专属库,核心逻辑依赖window对象,但Next.js默认开启服务端渲染(SSR),在服务端执行阶段不存在window,当你的自定义Hook在服务端初始化时调用Leaflet,就会触发该错误。
有效修复方案
1. 标记客户端组件(App Router)
在使用Leaflet Hook的组件或Hook文件顶部添加'use client'指令,强制该文件在客户端渲染:
'use client'; import { useLeafletMap } from './use-leaflet-map'; export default function MapPage() { useLeafletMap('map-container'); return <div id="map-container" style={{ height: '400px' }} />; }
同时确保use-leaflet-map.tsx和use-custom-map.tsx也添加该指令,避免服务端执行依赖window的代码。
2. 动态导入Leaflet及相关依赖
使用Next.js的next/dynamic动态导入地图组件,禁用SSR:
import dynamic from 'next/dynamic'; // 动态导入地图组件,服务端不渲染 const MapComponent = dynamic(() => import('../components/MapComponent'), { ssr: false, loading: () => <div>加载地图中...</div> }); export default function Home() { return <MapComponent />; }
在MapComponent内部再引入你的自定义Hook,确保Leaflet仅在客户端加载。
3. Hook内添加window存在性检查
在自定义Hook中,所有涉及Leaflet初始化的逻辑都包裹在typeof window !== 'undefined'判断中:
'use client'; import { useEffect } from 'react'; import L from 'leaflet'; export function useLeafletMap(mapId: string) { useEffect(() => { // 仅在客户端环境执行Leaflet初始化 if (typeof window === 'undefined') return; const map = L.map(mapId).setView([51.505, -0.09], 13); L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map); return () => map.remove(); }, [mapId]); }
4. 客户端动态加载Leaflet CSS
Leaflet的CSS也需确保在客户端加载,避免服务端渲染时样式报错:
'use client'; import { useEffect } from 'react'; export function useLeafletStyles() { useEffect(() => { import('leaflet/dist/leaflet.css'); }, []); }
在地图组件中调用该Hook即可。
内容的提问来源于stack exchange,提问作者Ali God
相关产品推荐
相关产品推荐

