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

Compatibility issue with leaflet v4 and React 18?

Open mberest opened this issue 2 years ago • 20 comments

I receive error that react-leaflet-markercluster is trying to use version 17 of react. leaflet v4 requires React 18.

mberest avatar May 05 '22 16:05 mberest

I'm having the same issue. Fresh project with simple sample code, will give me console errors.

      <MapContainer
        className="map-container"
        center={[49.8397, 24.0297]}
        zoom={6}
      >
        <TileLayer
          attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
          url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
        />
        <MarkerClusterGroup>
          <Marker position={[49.8397, 24.0297]} />
          <Marker position={[52.2297, 21.0122]} />
          <Marker position={[51.5074, -0.0901]} />
        </MarkerClusterGroup>
      </MapContainer>

vanillafrosty avatar May 13 '22 18:05 vanillafrosty

are you getting "invalid hook call" as well? and does it run if you remove the MarkerClusterGroup component?

roecc avatar May 17 '22 13:05 roecc

Yea, I was getting that. Removing MarkerClusterGroup removed the errors. I was able to bypass these errors by downgrading to React 17 and react-leaflet v3.2.5.

vanillafrosty avatar May 18 '22 18:05 vanillafrosty

haha, i did the same thing! ^^

roecc avatar May 18 '22 20:05 roecc

Yea, I was getting that. Removing MarkerClusterGroup removed the errors. I was able to bypass these errors by downgrading to React 17 and react-leaflet v3.2.5.

Did the same thing as you did, but still getting: Error: No context provided: useLeafletContext() can only be used in a descendant of <MapContainer>

can you share me your package.json file??

nasim38 avatar May 19 '22 13:05 nasim38

When will be fixed ? I need leaflet v4 and marker clustering

muratclk avatar Jun 07 '22 17:06 muratclk

I'd also need this component to be compatible with react 18 and react-leaflet 4 and to be usable with GeoJson :)

FabrizioPe avatar Jun 09 '22 12:06 FabrizioPe

Also need this component to be compatible with react 18 and react-leaflet 4. I'm appreciated for looking into the issue

changey avatar Jun 16 '22 19:06 changey

This library is actually a pretty thin wrapper around leaflet.markercluster: I got it working after

  1. npm install leaflet.markercluster that and then
  2. gently converted the current react-leaflet-markercluster.js to this, in components/MakeClusterGroup.ts (just remove the handful of type definitions to convert to JS):
import 'leaflet.markercluster';
import {createPathComponent} from '@react-leaflet/core';
import L from 'leaflet';

const MarkerClusterGroup = createPathComponent(({children: _c, ...props}, ctx) => {
  const clusterProps: Record<string, any> = {};
  const clusterEvents: Record < string, any >= {};

  // Splitting props and events to different objects
  Object.entries(props).forEach(([propName, prop]) => propName.startsWith('on') ? (clusterEvents[propName] = prop)
                                                                                : (clusterProps[propName] = prop));

  // Creating markerClusterGroup Leaflet element
  const markerClusterGroup = L.markerClusterGroup(clusterProps);

  // Initializing event listeners
  Object.entries(clusterEvents).forEach(([eventAsProp, callback]) => {
    const clusterEvent = `cluster${eventAsProp.substring(2).toLowerCase()}`;
    markerClusterGroup.on(clusterEvent, callback);
  });

  return {
    instance: markerClusterGroup,
    context: {...ctx, layerContainer: markerClusterGroup},
  };
});

export default MarkerClusterGroup;

Then here's my full components/myMap.tsx for completeness:

import "leaflet/dist/leaflet.css";
import "leaflet.markercluster/dist/MarkerCluster.css";
import "leaflet.markercluster/dist/MarkerCluster.Default.css";

import { MapContainer, Marker, Popup, TileLayer } from "react-leaflet";
import MarkerClusterGroup from "./MarkerClusterGroup";

interface MapStationsProps {
  latlons: [number, number][];
}
function MapStations({ latlons }: MapStationsProps) {
  const position = [51.505, -0.09] as [number, number];
  return (
    <MapContainer
      center={position}
      zoom={5}
      style={{ width: "100%", height: "600px" }}
    >
      <TileLayer
        attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
        url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
      />
      <Marker position={position}>
        <Popup>
          A pretty CSS3 popup. <br /> Easily customizable.
        </Popup>
      </Marker>
      <MarkerClusterGroup> // <-------------------------------------- !
        {latlons.map((v, i) => (
          <Marker key={i} position={v} />
        ))}
      </MarkerClusterGroup> // <-------------------------------------- !
    </MapContainer>
  );
}
export default MapStations;

Working with

  "dependencies": {
    "leaflet": "^1.8.0",
    "leaflet.markercluster": "^1.5.3",
    "next": "^12.1.6",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-leaflet": "^4.0.0",
  },

image

fasiha avatar Jun 18 '22 23:06 fasiha

maybe one can try https://www.npmjs.com/package/@changey/react-leaflet-markercluster for react 18 and leaflet v4 compatibility for now

changey avatar Jun 20 '22 21:06 changey

maybe one can try https://www.npmjs.com/package/@changey/react-leaflet-markercluster for react 18 and leaflet v4 compatibility for now

Does it support GeoJeson instead of Markers? Thanks!

FabrizioPe avatar Jun 21 '22 13:06 FabrizioPe

maybe one can try https://www.npmjs.com/package/@changey/react-leaflet-markercluster for react 18 and leaflet v4 compatibility for now

Do you also have @ŧypes for this?

voxelias avatar Jun 24 '22 20:06 voxelias

maybe one can try https://www.npmjs.com/package/@changey/react-leaflet-markercluster for react 18 and leaflet v4 compatibility for now

Does it support GeoJeson instead of Markers? Thanks!

Supports

kvengl avatar Jun 27 '22 14:06 kvengl

[with reach 18, leaflet 1.8 and react-leaflet 4] Tried to wrap my geoJson in marker cluster like:

<MarkerClusterGroup>
  <GeoJSON data={agentData} ref={geoJsonLayerRef} onEachFeature={visualData} />
</MarkerClusterGroup>

but I'm getting the "Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component." error. The code is inside a functional component, and the same error is thrown if I use three mock markers instead of the geojson. Any idea? I can't see which hook rules I'm breaking...

FabrizioPe avatar Jun 27 '22 20:06 FabrizioPe

[with reach 18, leaflet 1.8 and react-leaflet 4] Tried to wrap my geoJson in marker cluster like:

<MarkerClusterGroup>
  <GeoJSON data={agentData} ref={geoJsonLayerRef} onEachFeature={visualData} />
</MarkerClusterGroup>

but I'm getting the "Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component." error. The code is inside a functional component, and the same error is thrown if I use three mock markers instead of the geojson. Any idea? I can't see which hook rules I'm breaking...

Maybe your issue is related with this issue https://github.com/PaulLeCam/react-leaflet/issues/897 I think my issue above is related too

jaballogian avatar Jun 28 '22 02:06 jaballogian

https://github.com/changey/react-leaflet-markercluster works fine for me 🎉

barbalex avatar Jul 05 '22 12:07 barbalex

[with reach 18, leaflet 1.8 and react-leaflet 4] Tried to wrap my geoJson in marker cluster like:

<MarkerClusterGroup>
  <GeoJSON data={agentData} ref={geoJsonLayerRef} onEachFeature={visualData} />
</MarkerClusterGroup>

but I'm getting the "Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component." error. The code is inside a functional component, and the same error is thrown if I use three mock markers instead of the geojson. Any idea? I can't see which hook rules I'm breaking...

Maybe your issue is related with this issue PaulLeCam/react-leaflet#897 I think my issue above is related too

Sorry I'm a newbie in react, javascript, leaflet and so on and can't follow the details of the issue discussion. I've tried with the minimal example but couldn't get it to work... I'm not using hooks, so what could be the problem?

FabrizioPe avatar Jul 15 '22 17:07 FabrizioPe

@FabrizioPe The problem is that react-leaflet-markercluster provokes that hooks error when used with the newest versions of leaflet and react-leaflet. It is not your code.

You have two possible solutions:

  1. Use https://github.com/changey/react-leaflet-markercluster by installing yarn add @changey/react-leaflet-markercluster or npm install @changey/react-leaflet-markercluster instead of react-leaflet-markercluster. You can then switch back to react-leaflet-markercluster itself once it has solved this issue.
  2. Use the previous versions of leaflet (1.7.1) and react-leaflet (3.2.5). They work well with the current version of react-leaflet-markercluster

barbalex avatar Jul 15 '22 22:07 barbalex

@FabrizioPe The problem is that react-leaflet-markercluster provokes that hooks error when used with the newest versions of leaflet and react-leaflet. It is not your code.

You have two possible solutions:

  1. Use https://github.com/changey/react-leaflet-markercluster by installing yarn add @changey/react-leaflet-markercluster or npm install @changey/react-leaflet-markercluster instead of react-leaflet-markercluster. You can then switch back to react-leaflet-markercluster itself once it has solved this issue.
  2. Use the previous versions of leaflet (1.7.1) and react-leaflet (3.2.5). They work well with the current version of react-leaflet-markercluster

Thanks @barbalex for your simple explanation! I'll try the new package asap :)

FabrizioPe avatar Jul 24 '22 14:07 FabrizioPe

This issue sounds like it should be fixed with the code provided in this pull request or changey's release which incorporated my work to fix compatibily issues with Leaflet 4, React 18 and NextJS 12.

l4b4r4b4b4 avatar Aug 16 '22 18:08 l4b4r4b4b4