I'm learning Next.js and I'm having difficulties accessing the result of one of my API routes with getStaticProps
. The working API route produces an undefined
when I console.log
the props object in my component.
My API route returns a GeoJSON object from a Postgres database. I can access the results at localhost:3000/api/mymethod
, and I've tested the result in a GeoJSON validator.
I was able to construct my map with 2 components: a component for the map container itself and a second component for my Canvas layer. The map component is then imported into a page.
This is how I constructed the component for the Map Container:
import { MapContainer, TileLayer, Marker, Popup } from 'react-leaflet'
import 'leaflet/dist/leaflet.css'
import 'leaflet-defaulticon-compatibility/dist/leaflet-defaulticon-compatibility.css'
import 'leaflet-defaulticon-compatibility';
import LeafletCanvasMarker from './Pengs';
const Map = () => {
return (
<MapContainer center={[50.1109, 8.6821]} zoom={14} scrollWheelZoom={false} style={{height: "100vh", width: "100%"}}>
<TileLayer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
attribution="© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors"
/>
<Marker
position={[50.1109, 8.682]}
draggable={true}
animate={true}
>
</Marker>
<LeafletCanvasMarker />
</MapContainer>
)
}
export default Map
An this is my failing Canvas Layer component:
import { useEffect } from "react";
import { useMap } from "react-leaflet";
import "leaflet-canvas-marker";
import L from "leaflet";
export default function LeafletCanvasMarker({features}) {
console.log({features})
const map = useMap();
useEffect(() => {
if (!map) return;
var ciLayer = L.canvasIconLayer({}).addTo(map);
ciLayer.addOnClickListener(function (e, data) {
console.log(data);
});
ciLayer.addOnHoverListener(function (e, data) {
console.log(data[0].data._leaflet_id);
});
var icon = L.icon({
iconUrl: "https://unpkg.com/leaflet@1.7.1/dist/images/marker-icon.png",
iconSize: [20, 18],
iconAnchor: [10, 9],
});
ciLayer.addLayers({features});
}, [map]);
return null;
}
export async function getStaticProps() {
const data = await fetch('.api/getpoints').then(r => r.json())
return {
props:{ features }
}
}
Here is the page with the map component
import Head from 'next/head'
import dynamic from 'next/dynamic';
const mapPage = () => {
const MapWithNoSSR = dynamic(() => import("../components/Map"), {
ssr: false
});
return (
<div>
<Head>
<title>About</title>
</Head>
<h1>Map of Peng spots</h1>
<p>Map should go here!</p>
<MapWithNoSSR />
</div>
)
}
export default mapPage
My API route is defined in /api/getpoints
in an index.js
file with the following code:
export default async function handler(req, res) {
try{
const query = `SELECT json_build_object(
'type', 'FeatureCollection',
'features', jsonb_agg(feature)
)
FROM (
SELECT json_build_object(
'type', 'Feature',
'geometry', ST_AsGeoJSON(geom)::JSONB,
'properties', to_jsonb(inputs) - 'geometry'
) AS feature
FROM (
SELECT *
FROM public."Peng" AS p
JOIN public."Address_Info" AS i
ON p.id = i.id
) AS inputs
) AS features;`
const result = await conn.query(
query)
res.json(result.rows[0].json_build_object)
}
catch (error){
console.log(error);
}
}
When you visit localhost/api/getpoints
in the browser, valid GeoJSON is returned.
The code above worked with some dummy data, but I'm having issues with getting the API data into the component. Being relatively new to React and Next, I'm not sure where I have tripped up with this.