How to display geodjango rest api response on react leaflet Map - reactjs

I have the following response from django rest:
[
{
"area": 0.0,
"perimeter": 0.0,
"town_name": "Cheptais",
"town_id": 4,
"town_type": "Market Centres",
"geom": "SRID=4326;MULTIPOINT (34.4500007629395 0.800000011920929)"
},
{
"area": 0.0,
"perimeter": 0.0,
"town_name": "Dadaab",
"town_id": 3,
"town_type": "Trading Centre",
"geom": "SRID=4326;MULTIPOINT (40.3199996948242 0.070000000298023)"
},
{
"area": 0.0,
"perimeter": 0.0,
"town_name": "Eldas",
"town_id": 4,
"town_type": "Market Centres",
"geom": "SRID=4326;MULTIPOINT (39.5499992370605 2.52999997138977)"
}
]
Fetching the endpoint with axios this way:
await axios
.get("/api/gis/areas/", headers)
.then((response) => {
this.setState({ places: response.data });
console.log(response.data);
})
.catch(function (error) {
console.log(error);
});
}
const handleEachFeature = (feature, layer) => {
layer.bindPopup('<font size="4">' + feature.properties.town_name);
}
Using react leaflet, I create a map instance as follows:
<Map className="map" onEachFeature={handleEachFeature} style={{height:'100%',width:'100%'}}>
<GeoJSON data={places}/>
</Map>
However, this does not overlay the api response on my map.. I'm I missing something?

as i mentioned on the comments,you have to convert the wkt to geojson in order for this to work, there are several solution to achieve such conversion but the easiest one here is to import wicket library (just use npm install wicket), also you need to create the with a unique key, here is a working component from your same data (note i'm not using axios as i test the data locally), :
import React, { Component } from 'react'
import './styles/styles.css'
import {Map,TileLayer,GeoJSON} from 'react-leaflet'
import './leaflet/leaflet.css'
import Wkt from 'wicket'
import L from 'leaflet'
import Data from '../../Data/wkt_file.json'
import icon from 'leaflet/dist/images/marker-icon.png';
import iconShadow from 'leaflet/dist/images/marker-shadow.png';
// this is for maker to show up:
let DefaultIcon = L.icon({
iconUrl: icon,
shadowUrl: iconShadow
});
L.Marker.prototype.options.icon = DefaultIcon;
export default class map extends Component {
constructor(props){
super(props);
this.state={
wkt_json_holder:[],
json_ob:<></>,
json_key:1,
tile:'https://tiles.stadiamaps.com/tiles/alidade_smooth_dark/{z}/{x}/{y}{r}.png',
}
this.setGeoJSON = this.setGeoJSON.bind(this)
this.onEach = this.onEach.bind(this)
}
async componentDidMount(){
await this.setState({wkt_json_holder:Data});
this.setGeoJSON()
}
setGeoJSON=()=>{
let json_data = this.state.wkt_json_holder.map(point=>{
let wkt_geom = point['geom'].replace('SRID=4326;','')
let wkt = new Wkt.Wkt();
wkt.read(wkt_geom)
let geojson_geom = wkt.toJson()
let coords = geojson_geom['coordinates']
let type = geojson_geom['type']
let geojson_obj={
"type": "Feature",
"geometry": {
'type':type,
'coordinates':coords
},
"properties": {
"town_name": point['town_name'], "town_id": point['town_id'], "town_type":point['town_type'], "perimeter": point['perimeter'], "area": point['area']
}
}
return geojson_obj
}
)
console.log(json_data)
let json_ob= <GeoJSON data={json_data} key={1} style={{color:'red'}} onEachFeature={this.onEach}/>
this.setState({json_ob})
}
// handling Popups
onEach(feature,layer){
console.log(feature)
let PopupContent = `
<Popup>
<p>town id:${feature.properties.town_id}</p>
<p>town name:${feature.properties.town_name}</p>
</Popup>
`
layer.bindPopup(PopupContent)
}
render() {
return (
<div style={{width:'100%',height:'100%'}}>
<Map center={[2.197035, 38.703588]} zoom={6} style={{width:'100%',height:'100%'}}>
<TileLayer url={this.state.tile}/>
{this.state.json_ob}
</Map>
</div>
)
}
}

Related

React-mapbox-gl: Unable to hook into Mapbox API for adding 3D terrain to a map

I am using react-mapbox-gl in my next application, according to the documentation:
onStyleLoad: (map, loadEvent) => void called with the Mapbox Map
instance when the load event is fired. You can use the callback's
first argument to then interact with the Mapbox API.
This exposes a prop which allows one to interact with Mapbox API directly, and that has worked in regards to adding a Geocoder and GeoLocation Control but does not work in regards to adding 3d terrain.
This is my map component:
import { useCallback, useEffect, useRef } from 'react'
import ReactMapboxGl, { RotationControl, ZoomControl } from "react-mapbox-gl";
import mapboxgl from 'mapbox-gl';
import MapboxGeocoder from '#mapbox/mapbox-gl-geocoder';
const mapAccess = {
mapboxApiAccessToken: process.env.MAPBOX_ACCESS_TOKEN
}
const Map = ReactMapboxGl({
accessToken: process.env.MAPBOX_ACCESS_TOKEN,
logoPosition: 'bottom-right',
pitchWithRotate: true
});
export default function MyMap() {
return (
<>
<Map
style="mapbox://styles/mapbox/streets-v9"
onStyleLoad={(map) => {
map.addSource('mapbox-dem', {
'type': 'raster-dem',
'url': 'mapbox://mapbox.mapbox-terrain-dem-v1',
'tileSize': 512,
'maxzoom': 14
});
map.setTerrain({ 'source': 'mapbox-dem', 'exaggeration': 1.5 });
map.addLayer({
'id': 'sky',
'type': 'sky',
'paint': {
'sky-type': 'atmosphere',
'sky-atmosphere-sun': [0.0, 0.0],
'sky-atmosphere-sun-intensity': 15
}
}); map.on('load', () => {
console.log('load')
});
map.addControl(
new MapboxGeocoder({
accessToken: mapboxgl.accessToken,
mapboxgl: mapboxgl,
position: 'top-right'
})
);
map.addControl(
new mapboxgl.GeolocateControl({
positionOptions: {
enableHighAccuracy: true
},
trackUserLocation: true,
showUserHeading: true,
showAccuracyCircle: true,
position: 'top-left'
})
);
}}
>
<RotationControl className="mt-12" position="top-right" />
<ZoomControl className="mt-[2.375rem]" position="top-left" />
</Map>
</>
)
}
Any idea why this is not working?
Thanks in advance!

Getting updated coordinates after dragging in Leaflet

I am using react-leaflet and Leaflet.Path.Drag to drag GeoJSON. I would need to keep GeoJSON coordinations in React state. The issue is that updated coordinations on dragEnd are not corrent and GeoJSON position is not correct after dragging.
codesandbox.io
App.js
import React from "react";
import { MapContainer, GeoJSON, TileLayer, useMap } from "react-leaflet";
import "./styles.css";
import "leaflet/dist/leaflet.css";
require("leaflet-path-drag");
export default function App() {
const geoJSONRef = React.useRef(null);
const [coordinates, setCoordinates] = React.useState([
[-104.98569488525392, 39.63431579014969],
[-104.98569488525392, 39.64165260123419],
[-104.97161865234376, 39.64165260123419],
[-104.97161865234376, 39.63431579014969]
]);
const handleFeature = (layer) => {
layer.makeDraggable();
layer.dragging.enable();
layer.on("dragend", function (e) {
const latLngs = e.target.getLatLngs()[0];
console.log({ latLngs });
const coordinates = latLngs.map((point) => [point.lng, point.lat]);
geoJSONRef.current.eachLayer((geoLayer) => {
console.log(geoLayer.getLatLngs()[0]);
});
setCoordinates(coordinates);
});
};
const object = {
polygon: {
type: "FeatureCollection",
features: [
{
type: "Feature",
properties: {},
geometry: {
type: "Polygon",
coordinates: [[...coordinates]]
}
}
]
}
};
return (
<MapContainer center={[39.63563779557324, -104.99234676361085]} zoom={12}>
<TileLayer
attribution='&copy OpenStreetMap contributors'
url="https://{s}.tile.osm.org/{z}/{x}/{y}.png"
/>
<GeoJSON
key={`${coordinates}`}
ref={geoJSONRef}
data={object.polygon}
style={() => ({
color: "green",
weight: 3,
opacity: 0.5
})}
draggable={true}
pmIgnore={false}
onEachFeature={(feature, layer) => handleFeature(layer)}
></GeoJSON>
</MapContainer>
);
}
I am not sure why but e.target._latlngs[0] and e.target.getLatLngs()[0]; give a different result. Therefore if you try using the first expression it works as expected without moving further the dragged polygon
layer.on("dragend", function (e) {
const latLngs = e.target._latlngs[0]; // here replace the expression
const coordinates = latLngs.map((point) => [point.lng, point.lat]);
geoJSONRef.current.eachLayer((geoLayer) => {
// console.log(geoLayer.getLatLngs()[0]);
});
setCoordinates(coordinates);
});

how to create React search with multiple fields name

i am working on autocomplete with reactjs and react material-ui. Now its working on only one field name symbol but i want its work on multiple fields name like "symbol and name" Here is my working code and API response. API response filed name return row.symbol;
React search code
import React, { Component } from "react";
import Autocomplete from "./Autocomplete";
import { render } from "react-dom";
import ApiService from "../../service/ApiService";
const style = {
flexGrow: 1,
};
export class SearchScripComponent extends Component<any, any> {
constructor(props: any) {
super(props);
this.state = {
searchArray: [],
message: null,
};
this.searchScripData = this.searchScripData.bind(this);
}
componentDidMount() {
this.searchScripData(this.requesDATA2());
}
requesDATA2() {
let data1 = { symbolOrName: "TATA" };
return data1;
}
searchScripData(searchScrip: any) {
ApiService.searchScripDataList(searchScrip).then((res) => {
this.setState({ searchArray: res.data.data });
});
}
render() {
const suggestions = this.state.searchArray.map((row: any) => {
return row.symbol;
});
return <Autocomplete suggestions={suggestions} />;
}
}
export default SearchScripComponent;
API Data
{
"statusCode": 200,
"message": "SUCCESS",
"data": [
{
"scripId": 299,
"symbol": "TATAGLOBAL",
"name": "abc"
},
{
"scripId": 520,
"symbol": "TATAYODOGA",
"name": "ttp"
},
{
"scripId": 1195,
"symbol": "TATASPONGE",
"name": "eer"
},
{
"scripId": 30,
"symbol": "TATASTLBSL",
"name": "qwer"
}
]
}

REACT: add geojson data to deck.gl & react-map-gl

I am trying to graph a very simple data here https://raw.githubusercontent.com/pennytalalak/road-crash-data/master/src/data/output.geojson
But it wouldn't display the data on the map. Not sure if it is my geojson file or my code as my console said
Here is my code:
import React, { Component } from "react";
import { StaticMap } from "react-map-gl";
import DeckGL, { GeoJsonLayer } from "deck.gl";
//Mapbox Token
const MAPBOX_TOKEN =
"###########################";
//Geojson Data URL
const DATA =
"https://raw.githubusercontent.com/pennytalalak/road-crash-data/master/src/data/output.geojson";
const LIGHT_SETTINGS = {
lightsPosition: [-125, 50.5, 5000, -122.8, 48.5, 8000],
ambientRatio: 0.2,
diffuseRatio: 0.5,
specularRatio: 0.3,
lightsStrength: [2.0, 0.0, 1.0, 0.0],
numberOfLights: 2
};
const INITIAL_VIEW_STATE = {
latitude: -35.280937,
longitude: 149.130005,
zoom: 13,
pitch: 0,
bearing: 0
};
export default class Map extends Component {
renderLayer() {
const { data = DATA } = this.props;
return [
new GeoJsonLayer({
id: "geoJson",
data,
filled: true,
lightSettings: LIGHT_SETTINGS
})
];
}
render() {
const { viewState, baseMap = true } = this.props;
return (
<DeckGL
layers={this.renderLayer()}
initialViewState={INITIAL_VIEW_STATE}
viewState={viewState}
controller={true}
>
{baseMap && (
<StaticMap
mapStyle="mapbox://styles/mapbox/dark-v9"
preventStyleDiffing={true}
mapboxApiAccessToken={MAPBOX_TOKEN}
/>
)}
</DeckGL>
);
}
}

ReactJS: Fetching data from API

I'm having difficulties fetching data from an API in a React app with a simple standard template for fetching API data. The returned result from the console logs are blank arrays.
import React, {Component} from 'react';
import './App.css';
import Chart from './components/chart'
const API_URL = "http://ergast.com/api/f1/2016/1/results.json";
class App extends Component {
constructor(props) {
super(props)
this.state = {
results: [],
};
}
componentDidMount() {
fetch(API_URL)
.then(response => {
if (response.ok) {
return response.json()
}
else {
throw new Error ('something went wrong')
}
})
.then(response => this.setState({
results: response.MRData
})
)}
render() {
const {results} = this.state;
return (
<div className="App">
<Chart data={results}/>
</div>
);
}
}
export default App;
chart.js
import React from 'react';
import {XYPlot, XAxis, YAxis, VerticalGridLines, HorizontalGridLines, LineSeries} from 'react-vis';
const Chart = (props) => {
console.log(props.data);
const dataArr = props.data.map((d)=> {
return {x: d.RaceTable.Results.Driver.driverId, y: d.RaceTable.Results.position}
});
console.log(dataArr);
return (
<XYPlot
xType="ordinal"
width={1000}
height={500}>
<VerticalGridLines />
<HorizontalGridLines />
<XAxis title="Driver" />
<YAxis title="Race Finish Position" />
<LineSeries
data={dataArr}
style={{stroke: 'violet', strokeWidth: 3}}/>
</XYPlot>
);
}
export default Chart;
Really cannot figure out where I have gone wrong. I have set the state correctly with results: response.MRData isn't it? (MRData is the key of the JSON.) This is the structure of the json. API Link: http://ergast.com/api/f1/2016/1/results.json
JSON Example Response
{
"MRData": {
"xmlns": "http://ergast.com/mrd/1.0",
"RaceTable": {
"Races": [
{
"season": "2008",
"round": "1",
}
},
"Results": [
{
"position": "1",
"Driver": {
"driverId": "hamilton",
"permanentNumber": "44",
"code": "HAM",
"url": "http://en.wikipedia.org/wiki/Lewis_Hamilton",
"givenName": "Lewis",
"familyName": "Hamilton",
"dateOfBirth": "1985-01-07",
"nationality": "British"
},
}
},
.
.
.
]
}
]
}
}
}

Resources