325
325

Reputation: 606

What does "Error: There is already a source with this ID (Anonymous Function)" mean? (React, MapboxGL)

I have a small map application. When a user clicks the search button, I want the map to zoom into a specific area on the map and have a box appear. I am getting an error that there is already a source with this ID. What does this mean and how can I fix it?

const Map = (props) => {
  console.log(props);
  const mapContainerRef = useRef(null);

  const [lng, setLng] = useState(5);
  const [lat, setLat] = useState(34);
  const [zoom, setZoom] = useState(1.5);
  const [globalMap, setMap] = useState(Object());

  // Initialize map when component mounts
  useEffect(() => {
    const map = new mapboxgl.Map({
      container: mapContainerRef.current,
      style: 'mapbox://styles/mapbox/dark-v10',
      center: [lng, lat],
      zoom: zoom
    });

    setMap(map);

    // Disable default box zooming.
    map.boxZoom.disable();
    
    // Create a popup, but don't add it to the map yet.
    var popup = new mapboxgl.Popup({
      closeButton: false
    });

    // Add navigation control (the +/- zoom buttons)
    map.addControl(new mapboxgl.NavigationControl(), 'top-right');

    map.on('move', () => {
      setLng(map.getCenter().lng.toFixed(4));
      setLat(map.getCenter().lat.toFixed(4));
      setZoom(map.getZoom().toFixed(2));
    });

    map.on('load', function () {
    
    // function omitted to save space

    }

    // Clean up on unmount
    return () => map.remove(); 
  }, []); // eslint-disable-line react-hooks/exhaustive-deps

  React.useEffect(() => {
    if(props.show) {

      // Coordinates (eventually connect to back end)
      var northEast = [131.308594, 46.195042];
      var southEast = [117.597656, 8.233237];
      var southWest = [79.101563, 32.842674];
      var northWest = [86.847656, 44.715514];

      var maxSouth = Math.min(southEast[1], southWest[1]);
      var maxWest = Math.min(southWest[0], northWest[0]);
      var maxNorth = Math.max(northWest[1], northEast[1]);
      var maxEast = Math.max(northEast[0], southEast[0]);
      globalMap.fitBounds([
        [maxWest - 5, maxSouth - 5], // southwestern corner of the bounds
        [maxEast + 5, maxNorth + 5] // northeastern corner of the bounds
      ]); 
      
      // Add bounding box to the map
      // Defines bounding box
      // Polygons seem to be the preferred method according to my research
      globalMap.addSource('route', {
        'type': 'geojson',
        'data': {
            'type': 'Feature',
            'properties': {},
            'geometry': {
                'type': 'LineString',
                'coordinates': [
                    northEast, southEast, southWest, northWest, northEast
                ]
            }
        }
      });

      // Draws bounding box
      globalMap.addLayer({
        'id': 'route',
        'type': 'line',
        'source': 'route',
        'layout': {
            'line-join': 'round',
            'line-cap': 'round'
        },
        'paint': {
            'line-color': '#ff0000',
            'line-width': 5
        }
      });
    }
  });

The error occurs at the line globalMap.addSource('route', { .... It also shows the setLng, setLat, setZoom section.

Upvotes: 0

Views: 1346

Answers (2)

Amit
Amit

Reputation: 47

I solved this 'existing layer id' with adding

    return () => {
          mapRef.current.remove();
        };

before exiting the useEffect() block:

    useEffect(() =>{
    *your code here*

***add useEffect's return:***
return () => {
      mapRef.current.remove();
    };
    
    })

return(
***function return here*** 
(<div ref={mapContainerRef}
        className="map-container" />
)

Upvotes: 0

Titef
Titef

Reputation: 86

I am having the same issue. To my understanding, the source is getting added twice or more to the map because of some re render. You could also check if this source id exists or no before adding it. My temporary solution for now is to use React Mapbox gl components to render a layer.

Upvotes: 1

Related Questions