Reputation: 285
Since the mapbox map only seems to load properly in the useEffect hook, I don't see any other way of making the popup appear based on the parent's activeItem. If there are alternatives, please let me know!
const EmbeddedMap = ({ updateList, activeItem }) => {
const mapContainerRef = useRef(null)
const [list, setList] = useState([])
useEffect(() => {
const map = new mapboxgl.Map({
container: mapContainerRef.current,
accessToken: process.env.GATSBY_MAPBOX_TOKEN,
style: "mapbox://styles/mapbox/...",
center: [-90.836, 51.134],
zoom: 6,
})
const popup = new mapboxgl.Popup()
const getUniqueFeatures = (array, comparatorProperty) =>
array.filter(
(v, i, a) =>
a.findIndex(
t =>
t.properties[comparatorProperty] ===
v.properties[comparatorProperty]
) === i
)
const updateMap = map => {
const features = map.queryRenderedFeatures({ layers: ["data"] })
if (features) {
const uniqueFeatures = getUniqueFeatures(features, "post_id")
setList(uniqueFeatures)
}
}
map.on("load", () => {
updateMap(map)
map.on("movestart", () => {
map.setFilter("data", ["has", "title"])
})
map.on("moveend", () => {
updateMap(map)
})
map.on("mousemove", "data", e => {
map.getCanvas().style.cursor = "pointer"
const feature = e.features[0]
setPopup(map, popup, feature)
})
map.on("mouseleave", "data", () => {
map.getCanvas().style.cursor = ""
})
map.on("click", "data", e => {
const feature = e.features[0]
map.flyTo({
center: feature.geometry.coordinates[0],
})
setPopup(map, popup, feature)
})
})
return () => map.remove()
}, [])
return (
<div>
<EmbeddedMapStyled ref={mapContainerRef} />
</div>
)
}
Upvotes: 0
Views: 526
Reputation: 285
Changing my approach to a ref solved the problem:
const map = useRef(null)
map.current = new mapboxgl.Map({
container: mapContainerRef.current,
accessToken: process.env.GATSBY_MAPBOX_TOKEN,
style: "mapbox://styles/data",
center: [-114.836, 51.134],
zoom: 6,
})
Then I can easily reuse the map by using for example:
map.current.flyTo({
center: activeItem.startPoint,
})
Upvotes: 0