react-mapbox-gl
react-mapbox-gl copied to clipboard
GeoJSONLayer vs map.addLayer / Layer
Trying to understand the GeoJSONLayer component. I am fetching data and creating a geojson object on the fly on page render. I have set up a state to only render the map once the data has been set. However, I cannot get GeoJSONLayer to work.
No LineString renders:
<Map
style="{style}"
>
<GeoJSONLayer
data={geoJson}
lineLayout={{
visibility: "visible",
"line-join": "round",
"line-cap": "round",
}}
linePaint={{
"line-width": 6,
"line-color": "#f8f9fa",
}}
/>
</Map>
This renders the LineString:
<Map
style="{style}"
onStyleLoad={(map) => {
map.addLayer({
id: "routes",
type: "line",
source: {
type: "geojson",
data: geoJson.features[0],
},
});
}}
>
<Layer type="line" id="router" sourceId="routes" />
</Map>
Both methods are returned like this:
{geoJson ? (
<Map>...</Map>
):(<Loader />)}
What am I missing? I have tried it with smaller sample data that isn't fetched and the GeoJSONLayer still doesn't render.
Upon further inspection it looks like even doing a simple implementation it seems as though my map is rendering twice on the page and in neither instance is the controls or popup working...
This is driving me nuts. I will state. I am slowing building up complexity within React and this one has me stumped...
Component:
"use client";
import ReactMapboxGl, {
ZoomControl,
ScaleControl,
RotationControl,
Popup,
} from "react-mapbox-gl";
import "mapbox-gl/dist/mapbox-gl.css";
const Mapbox = ReactMapboxGl({
accessToken: process.env.NEXT_PUBLIC_MAPBOX_API_KEY,
});
export const Routes = () => {
return (
<Mapbox
style="mapbox://styles/mapbox/streets-v11"
containerStyle={{
height: "100vh",
width: "100%",
}}
onStyleLoad={(map) => console.log("Map loaded", map)}
>
<ZoomControl />
<ScaleControl />
<RotationControl />
<Popup
coordinates={[-0.13235092163085938, 51.518250335096376]}
offset={{
"bottom-left": [12, -38],
bottom: [0, -38],
"bottom-right": [-12, -38],
}}
>
<h1>Popup</h1>
</Popup>
</Mapbox>
);
};
Next.js / page.jsx
import { Routes } from "@/components/maps/routes";
export default function Index() {
return (
<>
<main>
<Routes />
</main>
</>
);
}
Update
It appears that Next.js is mounting, unmounting, and then mounting again so there is no cleanup of the initial <Mapbox/>
, thus the dual maps rendering on the page... A remove call was needed on the unmount on my end. To be clear, this only happens during local development not during production build/serve.