Skip to content

React-Leaflet Map doesn’t update

My issue is that react-leaflet <MapContainer> doesn’t center on a position that I set dynamically. The basic logic is that I have a form where I enter Street and House Number, then I make call for Nominatim and get some JSON format data, from where I extract latitude and longitude of a building. These lat and long I pass to my <MapContainer> but it doesn’t respond anyhow. With react-leaflet v2 with it was working pretty good, but after I updated to v3 it stopped.

Whenever I set default position values MapContainer centers on that position. But when I pass another value dynamically through Nominatim call it doesn’t work.

Here I make call for Nominatim:

const getSearchData = async () => {
    const exampleReq = `https://nominatim.openstreetmap.org/search/${query}?format=json&building=*&addressdetails=1&limit=1&polygon_geojson=1`;
    const response = await fetch(exampleReq);
    const data = await response.json();
    // console.log(data);
    if (data === undefined || data.length === 0) {
        // array empty or does not exist
        console.log("data array is empty");
        alert("Given address unrecognized! Try again please.")
        setLatitude(DEFAULT_LATITUDE);
        setLongitude(DEFAULT_LONGITUDE);
    }else{
        setLatitude(data[0].lat);
        setLongitude(data[0].lon);
    }
};

This is onSubmit of my form:

<form className={style.searchForm} onSubmit={e => {
                e.preventDefault();
                setQuery(street + " " + houseNumber.replace(///g, "-") + ", Tallinn");
                setPosition({
                    ltd: lat, 
                    lng: long
                });

And here is my MapBox component which contains my leaflet Map:

const MapBox = (props) => {

  useEffect(()=>{
      console.log("MAPBOX!");
      console.log("updateMap() - lat ---> " + props.latitude);
      console.log("updateMap() - long ---> " + props.longitude);
      updateMap();
  },[props.street, props.houseNumber]);

  const passStreet = props.street;
  const passHouseNumber = props.houseNumber;

  const updateMap = () => {
    // console.log("updateMap() - lat ---> " + props.latitude);
    // console.log("updateMap() - long ---> " + props.longitude);
    return(
        <MapContainer center={[props.latitude, props.longitude]} zoom={20}>
            <TileLayer
                url='https://{s}.tile.osm.org/{z}/{x}/{y}.png'
                attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
            />
            <OverpassLayer street={passStreet} houseNumber={passHouseNumber} />
        </MapContainer>
      );
  }

  return(
    updateMap()
  );
}

Answer

I was able to solve it. In documentation it is stated as:

Except for its children, MapContainer props are immutable: changing them after they have been set a first time will have no effect on the Map instance or its container. The Leaflet Map instance created by the MapContainer element can be accessed by child components using one of the provided hooks or the MapConsumer component.

This piece of code helps to understand:

function MyComponent() {
  const map = useMap()
  console.log('map center:', map.getCenter())
  return null
}

function MyMapComponent() {
  return (
    <MapContainer center={[50.5, 30.5]} zoom={13}>
      <MyComponent />
    </MapContainer>
  )
}

What I implemented:

function MyComponent(props) {
const map = useMap();
map.setView(props.center, props.zoom);
return null;
}