react-leaflet-markercluster icon indicating copy to clipboard operation
react-leaflet-markercluster copied to clipboard

Importing MarkerClusterGroup results in TypeError

Open reggie3 opened this issue 7 years ago • 38 comments

I am receiving the following error when trying to use this package.

TypeError: Super expression must either be null or a function, not object

The entire error is shown here: image

The error is associated with these lines of code in the react-leaflet-markcluster.js file (line numbers differ from what is shown in the error because of Chrome debugger formatting) image

I am trying to use the package in a Gatsby project, but I don't think that is causing the error. I am successfully able to import and use the react-leaflet project.

Version Info:

"react-leaflet": "^2.0.0",
"react-leaflet-markercluster": "^1.1.8",
"leaflet": "^1.3.1",
"leaflet.markercluster": "^1.3.0",
"gatsby": "^1.9.273",

Related Import Statements

import {
  Map,
  TileLayer,
  Marker,
  Popup,
} from 'react-leaflet';
import 'leaflet/dist/leaflet.css';
import MarkerClusterGroup from 'react-leaflet-markercluster/dist/react-leaflet-markercluster';
import 'react-leaflet-markercluster/dist/styles.min.css'; 

reggie3 avatar Jul 06 '18 09:07 reggie3

I have the same issue with:

"leaflet": "^1.3.1",
"leaflet.markercluster": "^1.3.0",
"react-leaflet": "^2.0.0-rc.3",
"react-leaflet-markercluster": "^1.1.8",

Is there a recommended version for these libraries?

oserban avatar Jul 06 '18 10:07 oserban

This plugin does not support react-leaflet v2.

yuzhva avatar Jul 06 '18 14:07 yuzhva

Any plans to update it to include v2 support?

ThiefMaster avatar Jul 06 '18 14:07 ThiefMaster

@ThiefMaster yep, I will try to deliver it during the next week. The trick is that react-leaflet was as the candidate release till that day.

So since today, I need to update this lib. I will update package.json dependency to solve that issue in v1.1.9.

And since v2.0 there will be support of react-leaflet ^2.0 latest React context from 16.3

yuzhva avatar Jul 06 '18 15:07 yuzhva

Temporary version:

import { MapLayer, withLeaflet } from "react-leaflet";
import L from "leaflet";

require("leaflet.markercluster");

class MarkerClusterGroup extends MapLayer {

  createLeafletElement(props) {
    const el = new L.markerClusterGroup(props);
    this.contextValue = {
      ...props.leaflet,
      layerContainer: el
    };
    return el;
  }

}

export default withLeaflet(MarkerClusterGroup);

webcarrot avatar Jul 06 '18 15:07 webcarrot

@webcarrot Many thanks for your contribution!

@reggie3 @oserban @ThiefMaster

Currently, the latest version with support of react-leaflet v2.0 and React 16.3 context API available as candidate release:

yarn add react-leaflet-markercluster@next # yarn
npm install react-leaflet-markercluster@next # npm

After the README and demo-app will be updated will publish it as release package.

P.S: it's stable and I think there would no be any changes in final release, so enjoy it (=

yuzhva avatar Jul 08 '18 07:07 yuzhva

Hi.

  1. In react-leaflet-markercluster@next version markers pop-ups do not display content - probably they need map from props.leaflet to be set/provided in MarkerClusterGroup instance contextValue.
  2. In my temporary version events handlers are "automagically" used by L.markerClusterGroup plugin so probably there is no need to reduce/filter/split props in createLeafletElement to handle events manually.
  3. This temporary version simply drop support for deprecated API (markers, options etc.).

Sorry for my English.

webcarrot avatar Jul 08 '18 13:07 webcarrot

@webcarrot

In react-leaflet-markercluster@next version markers pop-ups do not display content - probably they need map from props.leaflet to be set/provided in MarkerClusterGroup instance contextValue.

Yep, you are right. Already fixed it in 2.0.0-rc2 so it's published.

events handlers are "automagically" Just it's semantically inconveniently to use it. When you are writing some event handler on a cluster like:

<MarkerClusterGroup onClusterClick={} onCLusterMouseOver={} />

The repeating word Cluster seems superfluous

<MarkerClusterGroup onClick={} onMouseOver={} />

Gives a cleaner way of using props for event handlers.

yuzhva avatar Jul 09 '18 11:07 yuzhva

The 2.0.0-rc3 version works flawlessly with my use case. Thanks.

oserban avatar Jul 12 '18 13:07 oserban

I'm getting similar behavior and cannot get past it for the life of me.

"leaflet": "^1.3.2",
"leaflet.markercluster": "^1.3.0",
"react-leaflet": "^2.0.0",
"react-leaflet-markercluster": "^2.0.0-rc3",

I hit the error:

leaflet.markercluster-src.js?d09f:17 Uncaught ReferenceError: L is not defined
    at eval (leaflet.markercluster-src.js?d09f:17)
    at L.MarkerClusterGroup.L.FeatureGroup.extend.options.maxClusterRadius (leaflet.markercluster-src.js?d09f:8)
    at eval (leaflet.markercluster-src.js?d09f:11)
    at Object.<anonymous> (bundle.js:11987)
    at __webpack_require__ (bundle.js:20)
    at eval (react-leaflet-markercluster.min.js?a99b:1)
    at Object.<anonymous> (bundle.js:11976)
    at __webpack_require__ (bundle.js:20)
    at eval (MarkersLayer.js?ba8d:4)
    at Object.<anonymous> (bundle.js:11964)
(anonymous) @ leaflet.markercluster-src.js?d09f:17
L.MarkerClusterGroup.L.FeatureGroup.extend.options.maxClusterRadius @ leaflet.markercluster-src.js?d09f:8

If I add leaflet.js directly to the index.html Then I get the same error that started this thread.

react-leaflet-markercluster.min.js?a99b:1 Uncaught TypeError: Cannot read property 'markerClusterGroup' of undefined
    at t.value (react-leaflet-markercluster.min.js?a99b:1)
    at t.MapLayer (MapLayer.js?a679:24)
    at new t (react-leaflet-markercluster.min.js?a99b:1)
    at constructClassInstance (react-dom.development.js?cada:11447)
    at updateClassComponent (react-dom.development.js?cada:13144)
    at beginWork (react-dom.development.js?cada:13824)
    at performUnitOfWork (react-dom.development.js?cada:15863)
    at workLoop (react-dom.development.js?cada:15902)
    at HTMLUnknownElement.callCallback (react-dom.development.js?cada:100)
    at Object.invokeGuardedCallbackDev (react-dom.development.js?cada:138)

I'v tried @webcarrot's recommendation and still no dice. I have tried playing with 1000 different dependency combinations with no success clearing npm cache etc.

Kind at a loss right now. Any help is much appreciated.

webdobe avatar Jul 18 '18 01:07 webdobe

@webdobe

You need to install all peerDependencies:

yarn add leaflet.markercluster leaflet react-leaflet prop-types

Then install next release of that plugin:

yarn add react-leaflet-markercluster@next

Previously try to remove node_modules and clean all lock files if you have them to reset prev. versions.

yuzhva avatar Jul 18 '18 06:07 yuzhva

@YUzhva

Thank you soo much! I think I was missing prop-types when I was doing that exact same thing. I also ended up removing react and react-dom from my package.json and added that to the above just for good measure as it was complaining about my version of those as well.

webdobe avatar Jul 19 '18 18:07 webdobe

@YUzhva

I'm still getting the above error and I'm using 2.0.0-rc3

package.json

{
    "leaflet": "^1.4.0",
    "leaflet.markercluster": "^1.4.1",
    "react-leaflet": "^2.2.0",
    "react-leaflet-markercluster": "^2.0.0-rc3",
}

component

import { Map, CircleMarker, Tooltip, TileLayer } from 'react-leaflet';
import MarkerClusterGroup from 'react-leaflet-markercluster';

component.less

@import '~leaflet/dist/leaflet.css?url=false';
@import '~leaflet.markercluster/dist/MarkerCluster.css';
@import '~leaflet.markercluster/dist/MarkerCluster.Default.css';
@import '~react-leaflet-markercluster/dist/styles.min.css';

jwmann avatar Jan 16 '19 23:01 jwmann

Oddly, if I specifically use the dist version like the OP's example

import MarkerClusterGroup from 'react-leaflet-markercluster/dist/react-leaflet-markercluster';

It seems to work. (I had to set a maxZoom for the Map but that was a minor issue)

jwmann avatar Jan 16 '19 23:01 jwmann

For me, with react-leaflet 2 worked solution from #issuecomment-403071677 (WITHOUT USING THIS PACKAGE react-leaflet-markercluster)

import { MapLayer, withLeaflet } from '../src'
import L from "leaflet";

require("leaflet.markercluster");

class MarkerClusterGroup extends MapLayer {

  createLeafletElement(props) {
    const el = new L.markerClusterGroup(props);
    this.contextValue = {
      ...props.leaflet,
      layerContainer: el
    };
    return el;
  }

}

export default withLeaflet(MarkerClusterGroup);

Dependencies version:

    "react-leaflet": "2.2.1",
    "leaflet": "^1.4.0",
    "leaflet.markercluster": "^1.4.1",

adambisek avatar Feb 22 '19 13:02 adambisek

In case someone using Next.js stumbles upon here and use react-leaflet-universal (as I did), I confirm the rc3 works properly! You have to use next's dynamic() to import it client-side though.

import { Marker } from 'react-leaflet-universal'
//https://github.com/zeit/next.js/wiki/FAQ
//https://stackoverflow.com/questions/52939439/dynamic-import-node-module-with-next-js
import dynamic from 'next/dynamic'
const MarkerClusterGroup = dynamic(import('react-leaflet-markercluster'), {ssr: false})

...

<Map 
  //Custom component wrapping react-leaflet's Map, also loaded with dynamic()
  //Don't forget to add the maxZoom, or it'll die
  maxZoom={10} 
  >
    <MarkerClusterGroup>
        <Marker … />
        <Marker … />
        <Marker … />
    </MarkerClusterGroup>
</Map>

Deps :

    "leaflet": "^1.5.1",
    "leaflet.markercluster": "^1.4.1",
    "react-leaflet": "^2.3.0",
    "react-leaflet-markercluster": "^2.0.0-rc3",
    "react-leaflet-universal": "^2.1.0",

Bigood avatar Jun 25 '19 10:06 Bigood

"leaflet": "1.5.1",
"leaflet.markercluster": "1.4.1",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"react-leaflet": "2.3.0",
"react-leaflet-markercluster": "2.0.0-rc3",

I get the following error

The error: _leaflet2.default.markerClusterGroup is not a constructor

stereobooster avatar Oct 11 '19 16:10 stereobooster

import { MapLayer, withLeaflet } from "react-leaflet";
import "leaflet.markercluster";
import { MarkerClusterGroupProps } from "react-leaflet-markercluster";

// https://github.com/YUzhva/react-leaflet-markercluster/issues/71#issuecomment-466393028
class MarkerClusterGroup extends MapLayer {
  createLeafletElement(props: MarkerClusterGroupProps) {
    // @ts-ignore
    const el = new L.markerClusterGroup(props);
    this.contextValue = {
      ...props.leaflet,
      layerContainer: el,
    };
    return el;
  }
}

export default withLeaflet(MarkerClusterGroup);

gives this error

leaflet-src.js:1282 Uncaught TypeError: Cannot read property 'lat' of undefined
    at LatLngBounds.intersects (leaflet-src.js:1282)
    at e._recursively (leaflet.markercluster-src.js:1780)
    at e._recursivelyRemoveChildrenFromMap (leaflet.markercluster-src.js:1726)
    at e._moveEnd (leaflet.markercluster-src.js:931)
    at NewClass.fire (leaflet-src.js:593)
    at NewClass.panBy (leaflet-src.js:3313)
    at NewClass._tryAnimatedPan (leaflet-src.js:4592)
    at NewClass.setView (leaflet-src.js:3191)
    at Map.updateLeafletElement (Map.js:129)
    at Map.componentDidUpdate (Map.js:245)

UPD it seems I found why, because somehow leaflet resolves to different packages (hello webpack). As the result execution gets to this point:

function toLatLngBounds(a, b) {
	if (a instanceof LatLngBounds) {
		return a;
	}
	return new LatLngBounds(a, b);
}

where a is LatLngBounds (it has all the same methods), but it is not instance of LatLngBounds (it identifies itself as B).

Screenshot 2019-10-14 at 11 44 24

stereobooster avatar Oct 11 '19 16:10 stereobooster

@stereobooster I am stumbling upon the same problem, did you find any solution for this with Typescript?

saadsaifse avatar Mar 24 '20 16:03 saadsaifse

@saadsaifse end up using mapbox (with open source tiles)

stereobooster avatar Mar 24 '20 17:03 stereobooster

@stereobooster that's for the base layers I presume? How did you manage to get marker clustering without Leaflet?

saadsaifse avatar Mar 24 '20 17:03 saadsaifse

@saadsaifse first result from googling "mapbox cluster" https://docs.mapbox.com/mapbox-gl-js/example/cluster/

stereobooster avatar Mar 25 '20 12:03 stereobooster

I was also getting type errors, e.g. "TypeError: Cannot read property 'removeLayer' of undefined". However, using the code posted by @adambisek plus a css import, it seems to work. Here is the (slightly) modified code,

import { MapLayer, withLeaflet } from 'react-leaflet';
import L from "leaflet";

require("leaflet.markercluster");
require('react-leaflet-markercluster/dist/styles.min.css');

class MarkerClusterGroup extends MapLayer {

  createLeafletElement(props) {
    const el = new L.markerClusterGroup(props);
    this.contextValue = {
      ...props.leaflet,
      layerContainer: el
    };
    return el;
  }

}

export default withLeaflet(MarkerClusterGroup);

emilhe avatar Apr 16 '20 06:04 emilhe

@yuzhva i have same problems with below versions. I read all comments and tried a lot of things but i couldn't solve this problem. What should i try ?

  • "react-leaflet": "^2.2.1",
  • "leaflet.markercluster": "^1.4.1",
  • "leaflet": "1.4.0",
  • "react": "^16.8.1",
  • "react-dom": "^16.8.1",

Screen Shot 2020-08-31 at 09 59 40 Screen Shot 2020-08-31 at 10 00 16

umitduran avatar Aug 31 '20 07:08 umitduran

You are not supported to use v1.4.1 of this library with react-leaflet v2 and react ^16.

Try to remove and then add leaflet.markercluster again:

yarn remove leaflet.markercluster
yarn add leaflet.markercluster

leaflet.markercluster should be of v2.0.0

yuzhva avatar Aug 31 '20 08:08 yuzhva

You are not supported to use v1.4.1 of this library with react-leaflet v2 and react ^16.

Try to remove and then add leaflet.markercluster again:

yarn remove leaflet.markercluster
yarn add leaflet.markercluster

leaflet.markercluster should be of v2.0.0

@yuzhva are you sure leaflet.markercluster is possible with v2.0.0 because leaflet.markercluster latest version is 1.4.1 ?

umitduran avatar Aug 31 '20 12:08 umitduran

oh yeah, I mixed up leaflet.markercluster with this react-leaflet-markercluster package.

@umitduran what version of react-leaflet-markercluster are you using?

yuzhva avatar Sep 01 '20 07:09 yuzhva

@yuzhva my versions are below

  • "leaflet": "1.4.0",
  • "leaflet-draw": "^0.4.12",
  • "react": "^16.8.1",
  • "react-leaflet": "^2.2.1",
  • "react-leaflet-draw": "0.16.0",
  • "leaflet.markercluster": "^1.4.1",
  • "react-leaflet-markercluster": "^2.0.0-rc3",

umitduran avatar Sep 01 '20 08:09 umitduran

There is a new version of react-leaflet-markercluster available - v2.0.0

Did you try to remove -rc3 and use the latest one?

yarn remove react-leaflet-markercluster
yarn add react-leaflet-markercluster

yuzhva avatar Sep 01 '20 09:09 yuzhva

Hi all! I get the same issue. I'm using leaftlet to make some panels in grafana. First time I load my map, everything is fine, but if I go into another page with a map and then come back to my clustered map it's not reconizing my instanceof LatLngBounds in this code:

function toLatLngBounds(a, b) { if (a instanceof LatLngBounds) { return a; } return new LatLngBounds(a, b); }

NicoTechInc avatar Sep 17 '20 14:09 NicoTechInc