Search code examples
javascriptreactjsreact-leaflet

React-Leaflet always redraws the map with "MouseMove"


I want to display the geo coordinates when the mouse moves in my React app. I noticed that with "Mousemove" the map is repeatedly redrawn with all objects with a large number. How can I prevent this and only update the coordinates?

Here is the Code:

export class MapView extends Component {

state = {
lat: 10,
lon: 50,
tileName: "",
tiles: [],
};

MouseMove = () => {
const map = useMapEvent("mousemove", (e) => {
  let lon = e.latlng.lng;
  let lat = e.latlng.lat;

  this.setState({
    lat: lat.toFixed(6),
    lon: lon.toFixed(6),
    tileName: this.getTileNameSRTM(lon, lat),
  });
});
};

render() {
let self = this;
const matrix = this.props.matrix;

function renderMatrix() {
  if (matrix !== null) {
    return (
      <div>
        <Rectangle bounds={matrix.rect} pathOptions={{ color: "Blue" }} />
      </div>
    );
  }
}

function Zoom() {
  const map = useMapEvent("zoom", (e) => {
    console.log("zoom");
    self.drawTile(map, self);
  });
  return self.state.tiles;
}

function Pan() {
  const map = useMapEvent("move", (e) => {
    console.log("pan");
    //self.drawTile(map, self);
  });
  return self.state.tiles;
}

return (
  <div
    className="w3-col w3-margin-left w3-margin-right"
    style={{ width: "calc(80% - 2*16px)" }}
  >
    <div className="w3-container w3-blue w3-margin-top w3-margin-bottom w3-padding">
      <FontAwesomeIcon icon="fa-solid fa-map" className="w3-margin-right" />
      Map Viewer Latitude: {this.state.lat} Longitude: {this.state.lon}{" "}
      <label className="w3-right">{this.state.tileName}</label>
    </div>
    <MapContainer
      center={[50.65935313570456, 10.665137544640139]}
      zoom={5}
      style={{ height: "calc(100vh - 157.48px - 31px - 5*16px)" }}
      scrollWheelZoom={true}
    >
      <TileLayer
        attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
        url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
      />
      <this.MouseMove />
      <Zoom />
      <Pan />
    </MapContainer>
  </div>
 );
 }
}

export default MapView;

The source code is incomplete, I have only posted the affected parts.


Solution

  • This is the working code (as always read the manual first Leaflet React):

    function DisplayPosition({ map }) {
      const [position, setPosition] = useState(() => map.getCenter());
    
      const onMove = useCallback((e) => {
        setPosition(e.latlng);
      }, []);
    
      useEffect(() => {
        map.on("mousemove", onMove);
        return () => {
          map.off("mousemove", onMove);
        };
      }, [map, onMove]);
    
      return (
        <div className="w3-container w3-blue w3-margin-top w3-margin-bottom w3-padding">
          <FontAwesomeIcon icon="fa-solid fa-map" className="w3-margin-right" />
          Map Viewer Latitude: {position.lat.toFixed(6)} Longitude:{" "}
          {position.lng.toFixed(6)}{" "}
          <label className="w3-right">
            {self.getTileNameSRTM(position.lat, position.lng)}
          </label>
        </div>
      );
    }
    
    function FinalMap() {
      const [map, setMap] = useState();
    
      const displayMap = useMemo(
        () => (
          <MapContainer
            center={[50.65935313570456, 10.665137544640139]}
            zoom={5}
            style={{ height: "calc(100vh - 157.48px - 31px - 5*16px)" }}
            scrollWheelZoom={true}
            ref={setMap}
          >
            <TileLayer
              attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
              url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
            />
            <DrawTiles />
            <Greeting></Greeting>
          </MapContainer>
        ),
        []
      );
    
      return (
        <div>
          {map ? <DisplayPosition map={map} /> : null}
          {displayMap}
        </div>
      );
    }