Search code examples
reactjstypescriptleafletreact-leafletreact-leaflet-v4

Add more than one tile layers to <Mapcontainer> in react-leaflet


I want to add more than one tilelayers to mapcontainer. I am not able to accomplish that. I have one tilelayer like this

const magnifiedTiles = L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png")

and another one here:

export default function App(): JSX.Element {
 return (
<>
         <MapContainer center={center} zoom={13} scrollWheelZoom={true} style={{height: 'calc(100% - 30px)'}}>
 <TileLayer
      attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
      url='https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png' 
    /> 

</>)
}

I can either get a map reference from map container and use like magnifiedTiles.addTo(<map>)but I dont know how to get the map reference. Other option is addLayer(). However, I am not able to access it with from L.Tilelayer.

I know it leaflet it was as simple as getting map reference and using map.addLayer().


Solution

  • You can easily get the map reference via a ref in react-leaflet v.4.x

    const [map, setMap] = useState(null)
    
          <MapContainer
            center={center}
            zoom={zoom}
            scrollWheelZoom={false}
            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"
            />
          </MapContainer>
    

    and then use a useEffect to add any layer you want.

    useEffect(()=> {
    if (!map) return ;
    
    map.addLayer(...);
    },[])
    

    Edit after you added the typescript tag: Same as before only thing that changes you should install @types/react-leaflet and declare the map ref type.

    import { Map as MapProp, tileLayer } from "leaflet";
    ...
    const streets = tileLayer(
      "https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}",
      {
        attribution:
          '<a href="https://www.openstreetmap.org/">OpenStreetMap</a>, <a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, <a href="https://www.mapbox.com/">Mapbox</a>',
        maxZoom: 18,
        id: "mapbox/streets-v11",
        tileSize: 512,
        zoomOffset: -1,
        accessToken:
          ...
      }
    ); 
    

    Source for streets layer that includes token

    const [map, setMap] = useState<MapProp | null>(null);
    
    ...
    useEffect(() => {
        if (!map) return;
    
        map.addLayer(streets);
      }, [map]);
    

    Demo