shramov / leaflet-plugins

Plugins for Leaflet library
http://psha.org.ru/b/leaflet-plugins.html
MIT License
721 stars 289 forks source link

TypeError: Cannot read properties of undefined (reading 'remove') #307

Open sergaik-web opened 2 years ago

sergaik-web commented 2 years ago

Hi, I'm developing a modal window with an integrated leaflet map and I'm facing the same problem. When unmounting the modal window from DOM, with the Yandex map open, I get the following error.

Uncaught TypeError: Cannot read properties of undefined (reading 'remove')
    at NewClass.eval (Yandex.js?bafe:95:1)
    at NewClass.fire (leaflet-src.js?e11e:588:1)
    at NewClass.removeLayer (leaflet-src.js?e11e:6653:1)
    at NewClass.removeFrom (leaflet-src.js?e11e:6523:1)
    at NewClass.remove (leaflet-src.js?e11e:6512:1)
    at NewClass.remove (leaflet-src.js?e11e:3762:1)
    at eval (MapContainer.js?4686:48:1)
    at HTMLUnknownElement.callCallback (react-dom.development.js?61bb:3945:1)
    at Object.invokeGuardedCallbackDev (react-dom.development.js?61bb:3994:1)
    at invokeGuardedCallback (react-dom.development.js?61bb:4056:1)
    at flushPassiveEffectsImpl (react-dom.development.js?61bb:23543:1)
    at unstable_runWithPriority (scheduler.development.js?3069:468:1)
    at runWithPriority$1 (react-dom.development.js?61bb:11276:1)
    at flushPassiveEffects (react-dom.development.js?61bb:23447:1)
    at performSyncWorkOnRoot (react-dom.development.js?61bb:22269:1)
    at eval (react-dom.development.js?61bb:11327:1)
    at unstable_runWithPriority (scheduler.development.js?3069:468:1)
    at runWithPriority$1 (react-dom.development.js?61bb:11276:1)
    at flushSyncCallbackQueueImpl (react-dom.development.js?61bb:11322:1)
    at flushSyncCallbackQueue (react-dom.development.js?61bb:11309:1)
    at discreteUpdates$1 (react-dom.development.js?61bb:22420:1)
    at discreteUpdates (react-dom.development.js?61bb:3756:1)
    at dispatchDiscreteEvent (react-dom.development.js?61bb:5889:1)
the error leads here Yandex.js

Снимок экрана 2022-02-08 в 13 37 41

technology stack: ReactJs + NextJS + AntDesign

layer code

import 'leaflet-plugins/layer/tile/Yandex';
import {createLayerComponent, updateGridLayer} from '@react-leaflet/core';
import {useCallback, useEffect, useMemo, useState} from 'react';
import L from 'leaflet';
import PropTypes from 'prop-types';
import Script from 'next/script';

const YandexLayer = ({isTraffic}) => {
  const [isVisible, setVisible] = useState(false);

  useEffect(() => {
    if (window.ymaps) {
      setVisible(true);
    }
  }, []);

  const traffic = function () {
    //eslint-disable-next-line
    const actualProvider = new ymaps.traffic.provider.Actual({}, {infoLayerShown: true});

    actualProvider.setMap(this._yandex);
  };

  const createLeafletYandexElement = useCallback(
    (props, context) => {
      const instance = L.yandex();

      if (isTraffic) {
        instance.on('load', traffic);
      }

      return {instance, context};
    },
    [isTraffic]
  );

  const Yandex = useMemo(
    () => createLayerComponent(createLeafletYandexElement, updateGridLayer),
    [createLeafletYandexElement]
  );

  return (
    <>
      <Script
        onLoad={() => {
          setVisible(true);
        }}
        src="https://api-maps.yandex.ru/2.1/?lang=ru_RU&amp;apikey=****************"
      />
      {isVisible && <Yandex />}
    </>
  );
};

YandexLayer.propTypes = {
  isTraffic: PropTypes.bool.isRequired,
};

export default YandexLayer;

parent:

      <LayersControl position="topright" collapsed={false}>
        <LayersControl.BaseLayer checked={checkedLayer === Layers.YANDEX} name={Layers.YANDEX}>
          <YandexLayer isTraffic={isTraffic} />
        </LayersControl.BaseLayer>
      </LayersControl>

As I understand the problem occurs because the parent component is unmounted and _container becomes undefined. And the plugin does not have such a check, has anyone encountered a similar problem? Any solutions?

brunob commented 2 years ago

Hi, "the same problem" of which issue ? This one #303 ? <= if it's related to an existing issue, no need to create a new one :p