Home > other >  Changing leaflet basemaps with react buttons
Changing leaflet basemaps with react buttons

Time:01-05

I have two buttons and the idea is: when I click a button, it changes the basemap state. However, each time I click on the button to change the basemap tilelayer, I get

Error: Map container is already initialized.

Does anyone know of a way to fix this? My code is below.

useEffect(() => {
    console.log('Initializing map');
    var map = L.map(ref.current).setView([53.9, -9.5], 10);
    setLeafletMap(map);

    const osm = L.tileLayer(
      'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png',
      {
        attribution:
          '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors &copy; <a href="https://carto.com/attributions">CARTO</a>',
        subdomains: 'abcd',
        maxZoom: 20,
      }
    );
      const aerial = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
        {
          attribution:'Tiles &copy; Esri &mdash; Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community'
        }
      );
        const basemapLayers = {
                'OSM': osm, 
                'Aerial': aerial
            };
        basemapLayers[selectedBasemap].addTo(map);
  }, [selectedBasemap]);

CodePudding user response:

Obviously you should avoid reinitializing your map everytime you click on a different button.

Here the "difficulty" with React functional components is that it may not be obvious where to store that map and its Tile Layers. A solution is to use a useRef hook, which you populate at the component instanciation with a useEffect hook that runs only once (i.e. with an empty dependency array []).

Something in the lines of:

const leafletObjects = useRef();

useEffect(() => {
  leafletObjects.current = {
    map: L.map(ref.current),
    basemapLayers: {
      OSM: L.tileLayer(osmUrlTemplate),
      Aerial: L.tileLayer(aerialUrlTemplate)
    }
  };
}, []);

useEffect(() => {
  leafletObjects.current.basemapLayers[selectedBasemap].addTo(leafletObjects.current.map);
}, [selectedBasemap]);

Note: I see that you also used a state hook to store your map. It is also a valid solution, simply do the same with your Tile Layers.

CodePudding user response:

If you want to add a layer to your map you can do: map.addLayer(layer);

And if you want to remove / clean a layer before adding a new one you can map.removeLayer(layer);

See leaflet doc: https://leafletjs.com/reference.html

  •  Tags:  
  • Related