不能将 Leaflet 与 NextJS 一起使用

Can not use Leaflet with NextJS

我想在 NextJS(typescript) 中使用 Leaflet

但是Leaflet不支持SSR。所以,我使用 react-leaflet-univarsal.

然后,我自定义了Leaflet的Marker组件。所以,我想使用 Leaflet.Icon。 我尝试了两件事。

  1. if(process.browser){}

没有找到 window

  1. 使用 next/dynamic
  2. 的动态导入
let iconPerson: any;
  const DynamicComponent = dynamic(
    () =>
      import('leaflet').then(L => {
        iconPerson = (L as any).Icon.extend({
          options: {
            iconUrl: '/images/icon1.jpg',
            iconRetinaUrl: '/images/icon1.jpg',
            iconSize: new (L as any).Point(60, 75),
            className: 'leaflet-div-icon',
          },
        });
      }) as any,
    { ssr: false },
  );

....

<Marker icon={iconPerson}>

已打印。 > 无法读取未定义的 属性 'createIcon'

NextJS 使用 L.icon 的方法吗?

动态加载实际上只是针对组件,而不是库。

需要使用客户端 API 的库会在 SSR 中中断,但有一种方法可以解决这个问题。

首先,像往常一样导入库并在效果中使用它。效果仅在组件安装后在客户端上触发。

如果还是不行,你可以在效果中导入库。

请注意,如果您不使用功能组件,componentDidMount() 也是可行的。

在这种情况下(参见 relevant react docs on equivalents)componentDidMount() 的等价物是使用一个空数组:

useEffect(() => {
/* import the library like normal here if necessary */
/* use the library here */
}, []);

更多信息您可以查看FAQ

我用SSR地图组件解决了这个问题

特别是,

import * as React from 'react';
import { Map as M, TileLayer, Marker, Popup } from 'react-leaflet-universal';
import L from 'leaflet';
import { Pois } from '../types/pois';

const iconPerson = new L.Icon({
  iconUrl: '/images/icon1.svg',
  iconRetinaUrl: '/images/icon1.svg',
  iconAnchor: [20, 40],
  popupAnchor: [0, -35],
  iconSize: [40, 40],
});

const MAXIMUM_ZOOM = 18;

type Props = {
  position: { lat: number; lng: number };
  pois: Pois[];
};

const Map: React.FC<Props> = ({ position, pois }) => (
  <M center={position} zoom={MAXIMUM_ZOOM} doubleClickZoom={false}>
    <TileLayer
      attribution='copy <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
      url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
    />
    <Marker position={position} />
    {pois.map((poi: any) => (
      <Marker position={{ lat: poi.geo.x, lng: poi.geo.y }} icon={iconPerson} key={poi.id}>
        <Popup>{poi.description}</Popup>
      </Marker>
    ))}
  </M>
);

export default Map;

const Map: any = dynamic(() => import('./Map') as any, { ssr: false });

return <Map ... />

谢谢。