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

在Next.js中使用React-leaflet出现window未定义错误,求解决方案

解决Next.js中React-Leaflet的Window Undefined错误

问题根源

Next.js默认服务端渲染(SSR)环境不存在window对象,而React-Leaflet依赖浏览器环境的window,直接导入会导致服务端渲染阶段触发报错。

正确解决方案

1. 确保依赖安装

未安装依赖的话执行以下命令:

npm install react-leaflet leaflet
# 或
yarn add react-leaflet leaflet

2. 动态导入地图组件(禁用SSR)

用Next.js的dynamic工具导入地图组件,明确禁用服务端渲染,确保组件只在客户端加载。

在使用地图的页面文件(比如pages/map.js)中修改导入方式:

import dynamic from 'next/dynamic';

// 动态导入地图组件,禁用SSR
const OpenStreetMap = dynamic(() => import('../components/OpenStreetMap'), {
  ssr: false,
  loading: () => <div>加载地图中...</div> // 可选加载占位
});

export default function MapPage() {
  return <OpenStreetMap />;
}

3. 引入Leaflet样式

在pages/_app.js中全局引入Leaflet的CSS,否则地图瓦片会显示异常:

// pages/_app.js
import 'leaflet/dist/leaflet.css';

export default function App({ Component, pageProps }) {
  return <Component {...pageProps} />;
}

4. 修复Marker图标显示(可选)

如果Marker图标不显示,在地图组件中手动设置图标路径:

import L from 'leaflet';
delete L.Icon.Default.prototype._getIconUrl;

L.Icon.Default.mergeOptions({
  iconRetinaUrl: '/leaflet/images/marker-icon-2x.png',
  iconUrl: '/leaflet/images/marker-icon.png',
  shadowUrl: '/leaflet/images/marker-shadow.png',
});

需要把node_modules/leaflet/dist/images下的图标文件复制到项目public/leaflet/images目录中。

组件代码调整(可选)

如果不想拆分组件,也可以在组件内部通过useEffect确保仅在客户端渲染地图:

import React, { useRef, useState, useEffect } from "react";

const OpenStreetMap = () => {
  const [center, setCenter] = useState({
    lat: 23.729211164246585,
    lng: 90.40874895549243,
  });
  const mapRef = useRef();
  const [Map, setMap] = useState(null);
  const [TileLayer, setTileLayer] = useState(null);
  const [Marker, setMarker] = useState(null);
  const [Popup, setPopup] = useState(null);

  useEffect(() => {
    // 客户端动态导入react-leaflet组件
    const importComponents = async () => {
      const { Map, TileLayer, Marker, Popup } = await import('react-leaflet');
      setMap(Map);
      setTileLayer(TileLayer);
      setMarker(Marker);
      setPopup(Popup);
    };
    importComponents();
  }, []);

  const attribution =
    '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors';
  const url =
    "https://api.maptiler.com/maps/basic-v2/256/{z}/{x}/{y}.png?key=puoG6vOLC4oqJXcum8fR";

  if (!Map) return <div>加载地图中...</div>;

  return (
    <div style={{ height: '500px', width: '100%' }}> {/* 必须设置容器尺寸 */}
      <Map center={center} zoom={9} ref={mapRef} style={{ height: '100%' }}>
        <TileLayer attribution={attribution} url={url} />
        <Marker position={[23.729211164246585, 90.40874895549243]}>
          <Popup>This is a popup.</Popup>
        </Marker>
      </Map>
    </div>
  );
};

export default OpenStreetMap;

注意:地图容器必须设置明确高度,否则地图会无法显示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 12:25:42