1

I have a React Leaflet map that needs to change its center and zoom when given a set of markers. The zoom should be changed such that all the markers are visible.

This change of view is currently being attempted using the function ChangeView.

Using my code below, I am able to move the map view, but not able to let the map fit to the bounds. Running the code gives the error:

Error: Bounds are not valid.

on the line

map.fitBounds(markerBounds)

What can we do? Thanks!

import L, { LatLng, latLngBounds, FeatureGroup } from 'leaflet';
import React from 'react';
import { MapContainer, TileLayer, Marker, Popup, useMap } from 'react-leaflet';
import MarkerClusterGroup from 'react-leaflet-markercluster';

import { LatLon, MapMarker } from '../../common/types';
import { config } from '../../config';

interface IProps {
    markers: MapMarker[];
    searchCenter: LatLon;
}

interface IChangeView {
    center: LatLon;
    markers: MapMarker[];
}

function ChangeView({ center, markers }: IChangeView) {
    const map = useMap();
    map.setView({lng: center.lon, lat: center.lat}, DEFAULT_ZOOM);
    
    let markerBounds = latLngBounds([]);
    markers.forEach(marker => {
        markerBounds.extend([marker.lat, marker.lon])
    })
    map.fitBounds(markerBounds)   // <===== Error: Bounds are not valid.
    return null;
}


export function MapView({markers, searchCenter}: IProps): JSX.Element {
    
    return (
        <MapContainer
            center={[searchCenter.lat, searchCenter.lon]}
            zoom=14
            style={{ width:'100%', height:'100vh' }}
            className='markercluster-map'
        >
            <ChangeView center={searchCenter} markers={markers} />
            <TileLayer 
                url={`https://api.mapbox.com/styles/v1/mapbox/streets-v11/tiles/{z}/{x}/{y}?access_token=${config.api.mapbox}`}
            />
            <MarkerClusterGroup>
                {
                    markers.map((marker, index) => (
                        <Marker 
                            position={[marker.lat, marker.lon]} 
                            key={index}
                        />
                    ))
                }
            </MarkerClusterGroup>
        </MapContainer>
    )
}

Also tried using FeatureGroup instead of latLngBounds, but it gave the exact same error

Error: Bounds are not valid

    let group = new FeatureGroup();
    markers.forEach(marker => {
        L.marker([marker.lat, marker.lon]).addTo(group);
    })
    map.fitBounds(group.getBounds());
3
  • Can you do a console.log(markerBounds) right before map.fitBounds(markerBounds)? What does that give? Also, what does your markers array look like? Is there always values, or is it sometimes empty? Commented Jan 25, 2021 at 5:04
  • @SethLutske It's sometimes empty, and this is the problem. Thanks!
    – Nyxynyx
    Commented Jan 25, 2021 at 5:09
  • Do you only ever get this error when the markers array is empty? Commented Jan 25, 2021 at 5:14

1 Answer 1

2

If the markers array is empty, or null, the bounds you create will not have ._southWest and ._northEast properties, and that error will throw. Just make the fitBounds statement conditional on there being markers in the array:

if (markers.length && markers.length > 0){
  markers.forEach(marker => {
    markerBounds.extend([marker.lat, marker.lon])
  })
  map.fitBounds(markerBounds)
}

Or even just a quick one liner:

markerBounds.isValid() && map.fitBounds(markerBounds)

Not the answer you're looking for? Browse other questions tagged or ask your own question.