【问题标题】:Can not use Leaflet with NextJS不能将 Leaflet 与 NextJS 一起使用
【发布时间】:2020-03-06 11:17:29
【问题描述】:

我想在 NextJS(typescript) 中使用 Leaflet

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

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

  1. if(process.browser){}

找不到window

  1. 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 的方式吗?

【问题讨论】:

    标签: reactjs typescript leaflet next.js


    【解决方案1】:

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

    需要使用客户端 API 的库会在 SSR 中中断,但有办法解决此问题。

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

    如果这不起作用,您可以将库导入 in 效果。

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

    在这种情况下(参见relevant react docs on equivalents),componentDidMount() 的等效项是使用空数组:

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

    更多信息可以查看FAQ

    【讨论】:

    • 谢谢。但是,import L from 'leaflet' 无法通过错误“ReferenceError: window is not defined”来实现。
    • @wato9902 尝试在componentDidMount() 中导入库。 componentDidMount() { const { L } = require('leaflet'); }
    【解决方案2】:

    我通过 SSR Map 组件解决了这个问题。

    特别是,

    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 ... />
    

    谢谢。

    【讨论】:

    • 我做的和你完全一样,但是我有一个错误“Uncaught TypeError: promise.then is not a function”我想是因为当我做动态导入时,我使用require而不是import。你如何配置在客户端使用导入? @wato9902
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-24
    • 1970-01-01
    • 2020-08-17
    • 2021-09-15
    相关资源
    最近更新 更多