I am learning NextJS 14. My application is to display a leaflet map with some basic data. I've stated a new nextjs site using npx create-next-app@latest
.
I've found an example NextJS and Leaflet starter repo at https://github.com/colbyfayock/next-leaflet-starter. I've adapted the components in this repo to my own nextjs site.
When trying to understand how to approach the problem, I find React Leaflet: Add markers dynamically which looks like it applies to an older version of nextjs. I get the concept though - the markers get addded to a State variable, then iterate the same State variable when drawing on the map.
I can tell from the console log that the solution should be working, but the dynamically added marker is not drawn on the map.
page.jsx code below, github: https://github.com/timatlee/nextjs-leaflet
"use client"
import { Button } from '@/components/ui/button'
import Map from '@components/Map';
import React from 'react';
const DEFAULT_CENTER = [38.907132, -77.036546]
export default function Home() {
const [mapMarkers, setMapMarkers] = React.useState([[]])
function doSomethingFun() {
console.log("Start State ", mapMarkers)
setMapMarkers([DEFAULT_CENTER])
}
return (
<>
<Map className="mapcomponent" width="800" height="400" center={DEFAULT_CENTER} zoom={13}>
{({ TileLayer, Marker, Popup }) => (
<>
<TileLayer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
attribution="© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors"
/>
<Marker position={[DEFAULT_CENTER[0] + 0.01, DEFAULT_CENTER[1] + 0.01]}>
<Popup>
A dynamically added marker and popup.
</Popup>
</Marker>
{
mapMarkers.map((latlng) => {
if (latlng !== null) {
console.log("In map", latlng);
<Marker position={latlng}>
<Popup>
This popup should be offset from the dynamically drawn one.
</Popup>
</Marker>
}
})
}
</>
)}
</Map >
<p>Hello.</p>
<Button onClick={doSomethingFun}>Do something fun.</Button>
</>
)
}
Replace curly braces {} with parentheses () to properly return the Marker component in the mapMarkers.map function. And include the key prop for each dynamically added Marker.
It can be done as follow:
// ... (your imports)
export default function Home() {
const [mapMarkers, setMapMarkers] = React.useState([[]]);
function doSomethingFun() {
console.log("Start State ", mapMarkers);
setMapMarkers([...mapMarkers, [DEFAULT_CENTER[0] + 0.02, DEFAULT_CENTER[1] - 0.02]]);
}
return (
<>
<Map className="mapcomponent" width="800" height="400" center={DEFAULT_CENTER} zoom={13}>
{({ TileLayer, Marker, Popup }) => (
<>
<TileLayer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
attribution="© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors"
/>
<Marker position={[DEFAULT_CENTER[0] + 0.01, DEFAULT_CENTER[1] + 0.01]}>
<Popup>
A statically added marker and popup.
</Popup>
</Marker>
{mapMarkers.map((latlng, index) => (
latlng !== null && (
<Marker key={index} position={latlng}>
<Popup>
This popup should be offset from the dynamically drawn one.
</Popup>
</Marker>
)
))}
</>
)}
</Map>
<p>Hello.</p>
<Button onClick={doSomethingFun}>Do something fun.</Button>
</>
);
}