user122222
user122222

Reputation: 2419

Refresh leaflet map in react

I want to refresh circles of leaflet map after zoom:

import React from "react";
import {
  Map as LeafletMap,
  TileLayer,
  Marker,
  Circle,
  Tooltip,
  Popup
} from "react-leaflet";

import MarkerClusterGroup from "react-leaflet-markercluster";
import data from "./data.json";

const TILE_LAYER_ATTRIBUTION =
  "Map tiles by Carto, under CC BY 3.0. Data by OpenStreetMap, under ODbL";
const TILE_LAYER_URL =
  "https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png";

export function Map() {
  const position = [55.2854062,23.9327383];
  const initialZoom = 8;
  let showTooltip = false;
  let mapRef = React.createRef();

  const renderMarkers = () => {
    showTooltip = mapRef && mapRef.viewport && mapRef.viewport.zoom > 8 ? true : false;
    let circles = [];
    circles = data.map(item => (
      <Circle key={item.id}
        center={[item.latitude, item.longitude]}
        color="red"
        fillColor="red"
        radius={100}
      >
        <Tooltip className="circle-tooltip" permanent={true} direction={"center"}>
        {showTooltip ? <span>1</span> : <span></span>
      }
        </Tooltip>
        <Popup>
          <p>
            {item.address}, {item.city}
          </p>
          <p>{item.time}</p>
        </Popup>
      </Circle>
    ));

    return circles;
  };


  return (
    <LeafletMap ref={(ref) => { mapRef = ref }} center={position} zoom={initialZoom} onzoomend={() => renderMarkers() }>
      <TileLayer attribution={TILE_LAYER_ATTRIBUTION} url={TILE_LAYER_URL} />
      {
        <MarkerClusterGroup showCoverageOnHover={false}>
          {renderMarkers()}
        </MarkerClusterGroup>
      }
    </LeafletMap>
  );
}

however they are not being redrawn after the function renderMarkers() is called. What could be wrong here?

Upvotes: 1

Views: 5599

Answers (1)

kboul
kboul

Reputation: 14570

showTooltip should be a state variable using useState so when it changes component will rerender.

Moreover I think if you use functional components it should be useRef instead of createRef() and then

<LeafletMap
      ref={mapRef}
...

So it should be like this:

  let [showTooltip, setShowTooltip] = React.useState(false);
  let mapRef = React.useRef();

  const renderMarkers = () => {
    const map = mapRef.current;

    if (map) {
      console.log(map.leafletElement.getZoom());
      // change here the showTooltip flag
      setShowTooltip(map.leafletElement.getZoom() > 13 ? true : false);
    }
  };



<MarkerClusterGroup showCoverageOnHover={false}>
          {data.map(item => (
            <Circle
 ....
<MarkerClusterGroup/>

I changed slightly the example to have zoom bigger than 13 to show 1 and smaller not to show it to be able to demonstrate on the demo because in smaller zoom levels the bubble is displayed and you won't be able to see the tooltip.

Demo

Upvotes: 2

Related Questions