1

I'm having issue while rerendering the map with useEffect

  const [baseViewCoords, setBaseViewCoords] = useState([37.715, 44.8611]);

  const searchApiHandler = () => {
  // some code that will fetch new values for baseViewCoords and set to the state
  };

  useEffect(() => {

    var map = L.map('map').setView(baseViewCoords, 13);
    [](url)
    var osmLayer = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
        attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap<\/a> contributors'
    }).addTo(map);

    var stamenLayer = L.tileLayer('https://stamen-tiles- 
    {s}.a.ssl.fastly.net/watercolor/{z}/{x}/{y}.png', {
        attribution:
            'Map tiles by <a href="http://stamen.com">Stamen Design<\/a>, ' +
            '<a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0<\/a> &mdash; ' +
            'Map data {attribution.OpenStreetMap}',
        minZoom: 1,
        maxZoom: 16
    }).addTo(map)

    L.control.sideBySide(stamenLayer, osmLayer).addTo(map);
  }, [baseViewCoords]);

return (
     <div id="map" />
)

I'm trying to change the position of map and rerender it after fetching api but shows the in attached files enter image description here

Emad Baqeri
  • 2,333
  • 2
  • 14
  • 29

1 Answers1

2

This is happening because on mount, L.map is finding <div id="map" /> and initializing it to be a map. Then whenever your useEffect runs, it is trying to use that same div to run L.map again, but leaflet recognizes that that div is already a leaflet map, so it errors.

I recommend using actual react-lealfet components:

import { MapContainer, TileLayer } from 'react-leaflet';

const MyComponent = () => {

  const [baseViewCoords, setBaseViewCoords] = useState([37.715, 44.8611]);
  const [map, setMap] = useState();

  const searchApiHandler = () => {...};

  useEffect(() => {
    if (map){
      L.control.sideBySide(stamenLayer, osmLayer).addTo(map);
    }
  }, [map])

  useEffect(() => {
    if (map){
      map.setView(baseViewCoords)
    }
  }, [map, baseViewCoords]);

  return (
     <MapContainer
       center={baseViewCoords}
       zoom={13}
       whenCreated={map => setMap(map)}
     >
       <TileLayer 
         url={osm_url}
       />
       <TileLayer 
         url={stamen_url}
       />
     </MapContainer>
  )

}
Seth Lutske
  • 9,154
  • 5
  • 29
  • 78
  • I have changed my code but I'm still not able to make leaflet.sideBySide. I get Error below – Emad Baqeri Feb 22 '21 at 20:08
  • the error is Leaflet.sideBySide is not a function – Emad Baqeri Feb 23 '21 at 07:23
  • we should use L.control.slitMap( .. ).addTo(map) – Emad Baqeri Feb 23 '21 at 14:08
  • Ok...that's fine. I think you get the point though. You only want to add `L.control.splitMap` (or whatever its called) once the map exists. This useEffect should do the trick. Though based on your other question, it looks like you are doing a fair bit of work with react-leaflet, so I highly recommend getting comfortable building custom components for react-leaflet v3. You can check out the [official docs](https://react-leaflet.js.org/docs/core-architecture) on that, though I found them hard to follow, so you may also find [this post](https://stackoverflow.com/a/65713838/12010984) helpful. – Seth Lutske Feb 25 '21 at 04:34