react-map-gl
react-map-gl copied to clipboard
[Feat] Add onStyleImageMissing callback for Map
Target Use Case
Mapbox throws a warning when you try to load an image that hasn't been added.
Image [...] could not be loaded. Please make sure you have added the image with map.addImage() or a "sprite" property in your style. You can provide missing images by listening for the "styleimagemissing" map event.
They have a new map event, styleimagemissing
, that I think should be exposed by this React Wrapper. Unless this is already an event type that's supported with another callback handler that I've been overlooking.
Proposal
The usage might look something like this. I'm happy to help contribute in this feature if it's something that folks think would be good to add. I'll wait to hear back from a maintainer first though 😄
<Map
{...initialViewState}
mapboxAccessToken={MAPBOX_TOKEN}
projection={'globe'}
style={{ position: 'absolute', top: '0', bottom: '0', left: '0', right: '0' }}
onStyleImageMissing={evt => {
evt.target.loadImage(
"./icons/mapbox-marker-icon-20px-red.png",
(error, image) => {
if (error)
throw error;
evt.target.addImage(mapImages.Default, image);
}
);
}}
/>
Do you need to manipulate any React state in this callback? You can always add an event listener using a ref
to the map.
Yes, I can create an event listener for this specific event like this:
[...]
const mapRef = useRef();
const map = mapRef.current;
useEffect(() => {
if (map) {
map.on('styleimagemissing', () => {
if (!map.hasImage(id)) {
map.loadImage(
"./icons/mapbox-marker-icon-20px-red.png",
(error, image) => {
if (error) throw error;
if (!map.hasImage(id))
map.addImage(id, image);
}
);
}
});
}
}, [map]);
[...]
I guess what I'm trying to better understand is if this would be a desirable callback to add to react-map-gl. If it is not, could you try to explain to me why not? I don't have a strong opinion on the matter; I'm really new to MapBox (and react-map-gl, for that matter), so I'm just trying to better understand. Thank you in advance.
I don't have a strong opinion against this. Asking the question because there are dozens of other mapbox events that we don't have a React callback prop for. Should we add all of them? Is there any performance implication if we attach a listener to every event?
One possible argument for not having this prop is that, you do not need to manipulate any React state in the listener. You are technically "leaving" the React system.
Hey, thanks for this threat, which helped me to build my own useMissingImage
hook.
I thought I would share it as inspiration for others:
-
useMissingImage.ts
: https://github.com/FixMyBerlin/atlas-app/blob/develop/src/components/MapInterface/Map/utils/useMissingImage.ts - My docs on the topic an the file I use to map imageIds to actual images (same folder) https://github.com/FixMyBerlin/atlas-app/blob/develop/src/components/MapInterface/mapData/topicsMapData/mapboxStyleImages/README.md