Dynamic bounds change does not give any effect in 'react-leaflet'

1.8k views Asked by At

I encountered the problem while trying to use the react-leaflet's bounds property. My use case is that my application has some initial bounds defined in the state (let's say, fallback bounds), and those bounds are passed during the first render of component. The app architecture requires me to send request for the new bounds to set within the component, and here comes the problem.

On the example below (where I've simulated AJAX request using setTimeout) we can notice that the new bounds which are coming from request after timeout are not set at all, and I'm not quite sure why it's happening.

I suspect that is something with animation, because when increased timeout delay, the problem does not occur, and the second bounds are set correctly.

My setup:

"react": "17.0.0"
"leaflet": "1.6.0"
"react-leaflet": "2.7.0"
import React, { useState } from "react";
import { Map, ZoomControl, TileLayer } from "react-leaflet";

import "./styles.css";
import "leaflet/dist/leaflet.css";

export default function App() {
  const [bounds, setBounds] = useState([
    [75, -25],
    [30, 45]
  ]);

  setTimeout(() => {
    setBounds([
      [59.569068610511465, 10.387057922780514],
      [59.565111563593824, 10.397184267640114]
    ]);
  }, 200);

  return (
    <Map
      bounds={bounds}
      maxBounds={bounds}
      zoomControl={false}
      style={{
        height: 400,
        width: 400
      }}
    >
      <TileLayer
        url="//{s}.google.com/vt/lyrs=s&x={x}&y={y}&z={z}"
        maxZoom={21}
        minZoom={4}
        minZoomIsDrawing={18}
        subdomains={["mt0", "mt1", "mt2", "mt3"]}
      />
      <ZoomControl />
    </Map>
  );
}

Live example: https://codesandbox.io/s/keen-silence-vnt23

2

There are 2 answers

3
kboul On

You need to use an effect to get the map instance to change the map bounds.

Check here for more info.

const mapRef = useRef(null);

  useEffect(() => {
    const map = mapRef.current?.leafletElement;
    map.fitBounds([
      [59.569068610511465, 10.387057922780514],
      [59.565111563593824, 10.397184267640114]
    ]);
  }, []);

Demo

1
JohnS On

You can pass one of the value of the new bounds as a key on your MapContainer. React will consider that your map has changed and will rerendered it (be careful the component's state will be also reset).

https://beta.reactjs.org/apis/react/useState#resetting-state-with-a-key

<Map key={bounds[0][0]}>

You can also use the useMap hook, there is a topic about it: https://stackoverflow.com/questions/66839063/how-to-use-bounds-with-dynamic-markers-in-react-leaflet