alex3165 / react-mapbox-gl

A React binding of mapbox-gl-js
http://alex3165.github.io/react-mapbox-gl/
MIT License
1.93k stars 536 forks source link

onStyleLoad event only gets fired for the first style that is loaded #830

Open agusterodin opened 4 years ago

agusterodin commented 4 years ago

The onStyleLoad event only gets fired after the first style loads. If I change styles, the event never fires again like it should. Applying a callback to the underlying mapbox object directly does work and fires every time a new style is done loading.

This is a temporary workaround I came up with that works:

onStyleLoad={map => { setMapStyleLoaded(true) // Temporary workaround for the mapbox wrapper onStyleLoad function only being // fired the first time a style is ever loaded map.on('style.load', () => setMapStyleLoaded(true)) }}

Thanks for your hard work Alex!!! This is a superb Mapbox wrapper.

sergei-zelinsky commented 4 years ago

Hello there,

I face the same issue. The problem is because of the onStyleLoad callback is triggered by 'load' event instead of style.load one.

Here is the source code: https://github.com/alex3165/react-mapbox-gl/blob/master/src/map.tsx#L272-L280

I fixed that by manually attaching style.load event listener to the map object, like this:

// ...
const handleMapLoad = useCallback(map => {
    map.on('style.load', yourEventListener)
    // ...
}, []);

// ...
<Map
    onStyleLoad={handleMapLoad}
/>
// ...

Thanks

antonioOrtiz commented 2 years ago

Hi @sergei-zelinsky,

I am having a problem getting this functionality from the MAP GL JS API using the onStyleLoad prop to add 3d terrain to a map. I followed your prescription above with:

 export default function MyMap() {

  function handleLoadedMap(map) {
    map.addSource('mapbox-dem', {
      'type': 'raster-dem',
      'url': 'mapbox://mapbox.mapbox-terrain-dem-v1',
      'tileSize': 512,
      'maxzoom': 14
    });
    // add the DEM source as a terrain layer with exaggerated height
    map.setTerrain({ 'source': 'mapbox-dem', 'exaggeration': 1.5 });

    // add a sky layer that will show when the map is highly pitched
    map.addLayer({
      'id': 'sky',
      'type': 'sky',
      'paint': {
        'sky-type': 'atmosphere',
        'sky-atmosphere-sun': [0.0, 0.0],
        'sky-atmosphere-sun-intensity': 15
      }
    });
    map.addControl(
      new MapboxGeocoder({
        accessToken: mapboxgl.accessToken,
        mapboxgl: mapboxgl,
        position: 'top-right'

      })
    );

    map.addControl(
      new mapboxgl.GeolocateControl({
        positionOptions: {
          enableHighAccuracy: true
        },
        // When active the map will receive updates to the device's location as it changes.
        trackUserLocation: true,
        // Draw an arrow next to the location dot to indicate which direction the device is heading.
        showUserHeading: true,
        showAccuracyCircle: true,
        position: 'top-left'

      })
    );
  }

  const handleMapLoad = useCallback(map => {
    map.on('style.load', handleLoadedMap(map))
  }, []);

  return (
    <>
      <Map
        style="mapbox://styles/mapbox/streets-v9"
        onStyleLoad={handleMapLoad}
      >
        <RotationControl
          className="mt-12"
          position="top-right"
        />
        <ZoomControl
          className="mt-[2.375rem]"
          position="top-left"
        />
      </Map>
    </>
  )
}

All the other functions in there work i.e. `GeolocateControl` and  `MapboxGeocoder`.

Would you have any ideas?
antonioOrtiz commented 2 years ago

@sergei-zelinsky Nevermind I didn't pan it!