Не могу использовать Leaflet с NextJS - PullRequest
1 голос
/ 10 ноября 2019

Я хочу использовать Leaflet с NextJS (машинопись).

Но доза Leaflet не поддерживает SSR. Итак, я использую react-leaflet-univarsal.

Затем я использую маркерный компонент Leaflet. Итак, я хочу использовать Leaflet.Icon. Я пробовал 2 вещи.

  1. 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' из неопределенного

. Способ использования L.icon с NextJS?

Ответы [ 2 ]

1 голос
/ 10 ноября 2019

Динамическая загрузка на самом деле только для компонентов, а не для библиотек.

Библиотеки, которые требуют использования API на стороне клиента, прекратят работу в SSR, но есть способ обойти это.

Во-первых,импортируйте библиотеку как обычно и используйте ее в качестве эффекта. Эффекты запускаются на клиенте только после монтирования компонента.

Если это не сработает, вы можете импортировать библиотеку в эффект.

Обратите внимание, что componentDidMount () также жизнеспособен, если вы не используете функциональный компонент.

Эквивалент для componentDidMount () в этом сценарии (см. соответствующие документы реагирования на эквиваленты *)1014 *) будет использовать пустой массив:

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

Для получения дополнительной информации вы можете увидеть FAQ .

0 голосов
/ 11 ноября 2019

Я решил эту проблему с помощью компонента Карта 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 ... />

Спасибо.

...