I am encountering Uncaught (in promise) Error: Unsupported GeoJSON type: undefined. I am rendering it in OpenLayers using a MERN application. I have checked that the API call for the GeoJSON is returning correctly the data, though I am not sure if it is the right format. Could you check my code if this is the correct way to read and render the data? I have checked similar issues and they suggest to change the projection. Is my projection right? Or is it the way I store the data in the database that is the issue?
DataLayer.jsx
import { useEffect, useState } from "react";
import VectorSource from "ol/source/Vector";
import VectorLayer from "ol/layer/Vector";
import GeoJSON from "ol/format/GeoJSON";
const DataLayer = ({ map, layerType }) => {
const [layers, setLayers] = useState([]);
useEffect(() => {
const fetchData = async () => {
if (layerType === 'fireIncident') {
const res = await fetch(`/api/fire_incident`);
const data = await res.json();
if (data && data.length > 0 ) {
const wktOptions = {
featureProjection: 'EPSG:3857'
}
const vectorSource = new VectorSource({
features: new GeoJSON().readFeatures(data, wktOptions),
});
console.log('GeoJSON data:', data)
const vectorLayer = new VectorLayer({
source: vectorSource,
});
map.addLayer(vectorLayer);
setLayers((layers) => [...layers, vectorLayer]);
}
}
};
fetchData();
}, [map, layerType]);
return null;
};
export default DataLayer;
Basemap.jsx
import { useEffect, useRef, useState } from "react";
import Map from 'ol/Map';
import View from 'ol/View';
import TileLayer from "ol/layer/Tile";
import XYZ from 'ol/source/XYZ';
import { fromLonLat } from "ol/proj";
import 'ol/ol.css';
const BaseMap = ({ center, zoom, children }) => {
const mapElement = useRef();
const [map, setMap] = useState(null);
useEffect(() => {
const initialMap = new Map({
target: mapElement.current,
layers: [
new TileLayer({
source: new XYZ({
url: 'https://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png',
crossOrigin: 'anonymous',
}),
}),
],
view: new View({
center: fromLonLat(center),
zoom: zoom,
}),
});
setMap(initialMap);
return () => initialMap.setTarget(null);
}, [center, zoom]);
return (
<div id="map" ref={mapElement} style={{ width: '100%', height: '100vh' }}>
{children(map)}
</div>
);
};
export default BaseMap;
Here is the GeoJSON data from the API call which returns 2 results:
[{"properties":{"incyr":2019,"month":"February","penro":"PPG","cenro":"","location":"Brgy Diaz","occur_date":"2019-02-10T00:00:00.000Z","cause":2,"area_damage":1},"geometry":{"type":"Point","coordinates":[120.51350683576823,15.099785805351729]},"_id":"6547bc4174377cd1cbd44415","type":"Feature","__v":0},{"properties":{"incyr":2020,"month":"March","penro":"PPG","cenro":"","location":"San Vicente","occur_date":"2020-03-29T00:00:00.000Z","cause":1,"area_damage":0.5},"geometry":{"type":"Point","coordinates":[120.73099597560082,15.233933632945224]},"_id":"6547bc6174377cd1cbd44417","type":"Feature","__v":0}]
Mongoose schema:
const fireIncidentSchema = new mongoose.Schema({
type: {
type: String,
enum: ['Feature'],
required: true
},
properties: {
incyr: Number,
month: String,
penro: String,
cenro: String,
location: String,
occur_date: Date,
cause: Number,
area_damage: Number
},
geometry: {
type: {
type: String,
enum: ['Point'],
required: true
},
coordinates: {
type: [Number],
required: true
}
}
});