I'm using Mapbox and in my localhost, it always loads my markers correctly. However now that I deployed my app, it doesn't.
At least sometimes,
I have noticed that if I load the page, and then just before the page loads, I switch to another tab and then wait 5 seconds, and then go back to the tab where my app is. It does work and loads the markers.
Also, I get the error: The source 'users' does not exist in the map's style. when I try to set a feature state(when you hover over sidebar items in the case that the markers did not load):
map.setFeatureState({source: 'users', id: i}, { hover: true})
I've also noted that the map.on('load', fn) is not firing when the markers are not loaded, because if I add a console.log inside it.. it won't get logged(when the markers did not load)
So the source is not loaded...
So, I'm guessing its some type of asynchronous problem, or maybe an issue with map.on('load', fn) might suffer from some race condition: https://github.com/mapbox/mapbox-gl-js/issues/6707.
That's why when I give it some time, by going to another tab, and then coming back, it works.
But I can't think of a solution.
I have this loadUsers function, which makes an API call to my backend, gets the users, and then calls the map.on('load', fn)
And im using await when i get the users:
const res = await axios.get(`${apiUrl}?lat=${lat}&lng=${lng}`)
const users = res.data;
...
can anyone see where the issue is? why my markers are not loading?
My site live is here: https://jamsesssion.com/
You could see the code there if you inspect and search for the file: usersMap.js by pressing cmd+p in the chrome console and searching for the file.
And this is the code:
async function loadUsers(map, lat = 52.5, lng = 13.4, apiUrl = `/api/users/near?lat=${lat}&lng=${lng}`) {
const res = await axios.get(`${apiUrl}?lat=${lat}&lng=${lng}`)
const users = res.data;
if (!users.length) {
alert('Oooops! \n\nThere are no registered users in the place you searched yet, If you live there, register to Jamsession and tell your friends!');
return;
}
const geoJsonMarkers = users.map( (place, i ) => {
const [placeLng, placeLat] = place.location.coordinates;
const position = { lat: placeLat, lng: placeLng };
return {
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [position.lng, position.lat]
},
'id': i,
'properties': {
'name': place.name,
'genres': place.genres,
'photo': place.photo,
'slug': place.slug,
}
}
})
let markers = { 'features': geoJsonMarkers }
map.on('load', function() {
map.addSource('users', {
type: "geojson",
data: markers,
cluster: true,
clusterMaxZoom: 22,
clusterRadius: 50,
})
map.addLayer({
id: "singles",
type: "circle",
source: "users",
filter: ["!has", "point_count"],
paint: {
'circle-radius': {
'base': 10,
'stops': [[5, 20], [13, 50], [14, 60]]
},
// 'circle-color': '#ddffc8',
'circle-color': ["case",
["boolean", ["feature-state", "hover"], false],
'#ff4da6',
'#ddffc8'
],
}
});
}
map.on('load'..)request outside of the loadUsers function so that the map waits for theloadUsersrequest to finish. You can also create a separate function to add the source and layers that also waits for theloadUsersrequest. So it could look something like:map.on('load', function () { loadUsers(addSources) });- geografa