不能将 Leaflet 与 NextJS 一起使用
Can not use Leaflet with NextJS
我想在 NextJS(typescript) 中使用 Leaflet
。
但是Leaflet不支持SSR。所以,我使用 react-leaflet-univarsal
.
然后,我自定义了Leaflet的Marker组件。所以,我想使用 Leaflet.Icon
。
我尝试了两件事。
if(process.browser){}
没有找到 window
。
- 使用
next/dynamic
的动态导入
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 ... />
谢谢。
我想在 NextJS(typescript) 中使用 Leaflet
。
但是Leaflet不支持SSR。所以,我使用 react-leaflet-univarsal
.
然后,我自定义了Leaflet的Marker组件。所以,我想使用 Leaflet.Icon
。
我尝试了两件事。
if(process.browser){}
没有找到 window
。
- 使用
next/dynamic
的动态导入
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 ... />
谢谢。