How to query routes in here maps with reactjs - reactjs

I am trying to make map queries with here maps on routes with reactjs, currently I can display the map in my application with this code:
import * as React from 'react';
export const DisplayMapFC = () => {
// Create a reference to the HTML element we want to put the map on
const mapRef = React.useRef(null);
/**
* Create the map instance
* While `useEffect` could also be used here, `useLayoutEffect` will render
* the map sooner
*/
React.useLayoutEffect(() => {
// `mapRef.current` will be `undefined` when this hook first runs; edge case that
if (!mapRef.current) return;
const H = window.H;
const platform = new H.service.Platform({
apikey: "xxxxxxxxx"
});
const defaultLayers = platform.createDefaultLayers();
const hMap = new H.Map(mapRef.current, defaultLayers.vector.normal.map, {
center: { lat: 36.2104063, lng: -113.7236071 }, //,
zoom: 4,
pixelRatio: window.devicePixelRatio || 1
});
const behavior = new H.mapevents.Behavior(new H.mapevents.MapEvents(hMap));
const ui = H.ui.UI.createDefault(hMap, defaultLayers);
// This will act as a cleanup to run once this hook runs again.
// This includes when the component un-mounts
return () => {
hMap.dispose();
};
}, [mapRef]); // This will run this hook every time this ref is updated
return <div className="map" ref={mapRef} style={{ height: "355px",width:"650px" }} />;
};
const searchMap=(e)=>{
e.preventDefault();
console.log(" view controle ",e);
const origin="52.5308,13.3847";
const destiny="52.5264,13.3686";
}
I am trying to send coordinates from a start point to an end point so that I can show the plotted route and time

this worked for me:
Change API_KEY, origin and destination. Luck!
https://codesandbox.io/s/react-with-heremap-2cze0?file=/src/mapHere.js

Related

Mapbox geocoder in React

I recently made my first app on React. I had a d3 map that looks a bit old now, so I decided to switch to Mapbox.
The data transmitted is a list of country names and a percentage. The goal is to visualize each country and its percentage.
I wrote all my code, and everything seemed to go well.
However, I now get this error on line 19 : "Geocoder is not defined".
I specify that I have installed :
mapbox-gl
react-mapbox-gl
react-map-gl-geocoder
Can someone explain to me where my mistake came from?
import React, { useRef, useEffect } from "react";
import mapboxgl from "mapbox-gl";
import MapGeocoder from "react-map-gl-geocoder";
const MapChart = ({ data }) => {
const mapContainer = useRef(null);
useEffect(() => {
mapboxgl.accessToken =
"**********";
const map = new mapboxgl.Map({
container: mapContainer.current,
style: "mapbox://styles/mapbox/streets-v12",
center: [0, 0],
zoom: 1
});
// Geocode the data points to get the latitude and longitude
const geocoder = new MapGeocoder({
accessToken: mapboxgl.accessToken
});
data.forEach((datapoint) => {
geocoder.geocode(datapoint.country, (error, result) => {
if (error) {
console.error(error);
return;
}
const [longitude, latitude] = result.features[0].geometry.coordinates;
const marker = new mapboxgl.Marker({
color: "#" + ((Math.random() * 0xffffff) << 0).toString(16)
}).setLngLat([longitude, latitude]);
marker.setPopup(
new mapboxgl.Popup().setHTML(`
<h3>${datapoint.country}</h3>
<p>${datapoint.percentage}%</p>
`)
);
marker.addTo(map);
});
});
}, [data]);
return <div ref={mapContainer} style={{ width: "100%", height: "400px" }} />;
};
export default MapChart;
You are actually using the MapboxGeocoder from '#mapbox/mapbox-gl-geocoder'. If you intend to use the one provided by react-map-gl-geocoder, it would work slightly differently.

How to make dynamic changes in Arcgis JS map-component with React?

I am quite new to Arcgis-JS and React. As suggested here, I am using a functional component with the useEffect hook to integrate my map.
Now I want to display a line within my map when I click on a certain row of a list. On click I am fetching the appropriate coordinates to be displayed and storing them to a context-variable (dbPageContext.currentGeom).
The problem: When I want to display another line, the entire map-component has to re-render as I am passing the line-array-variable as a second argument to the useEffect hook.
const MapComp = () => {
const mapRef = useRef();
const dbPageContext = useContext(DbPageContext);
useEffect(() => {
const mainMap = new Map({
layers: [layer],
basemap: "arcgis-topographic", // Basemap layer service
});
const graphicsLayer = new GraphicsLayer();
mainMap.add(graphicsLayer);
const polyline = {
type: "polyline",
paths: dbPageContext.currentGeom,
};
const simpleLineSymbol = {
type: "simple-line",
color: [0, 230, 250],
width: 4,
};
const polylineGraphic = new Graphic({
geometry: polyline,
symbol: simpleLineSymbol,
});
graphicsLayer.add(polylineGraphic);
const view = new MapView({
container: mapRef.current,
map: mainMap,
spatialReference: {
wkid: 3857,
},
});
return () => {
view && view.destroy();
};
}, [dbPageContext.currentGeom]);
return (
<div>
<div className="webmap" ref={mapRef} />
</div>
);
};
export default MapComp;
How can I update only the graphics-layer without updating the entire map-component? Would be great if someone could help me finding a solution for that.
EDIT: I also tried to implement the map without using the useeffect hook. But then, nothing was displayed.
You need to separate the effects. On page load, you should have one effect that creates the map. Then a second effect can update the map when dbPageContext.currentGeom changes.
const MapComp = () => {
const mapRef = useRef();
const dbPageContext = useContext(DbPageContext);
// Memoize this, as you only need to create it once, but you also need
// it to be available within scope of both of the following useEffects
const graphicsLayer = React.useMemo(
() => new GraphicsLayer(),
[]
);
// On mount, create the map, view, and teardown
useEffect(() => {
const mainMap = new Map({
layers: [layer],
basemap: "arcgis-topographic", // Basemap layer service
});
const view = new MapView({
container: mapRef.current,
map: mainMap,
spatialReference: {
wkid: 3857,
},
});
mainMap.add(graphicsLayer);
return () => {
view && view.destroy();
};
}, [])
// When dbPageContext.currentGeom changes, add a polyline
// to the graphics layer
useEffect(() => {
const polyline = {
type: "polyline",
paths: dbPageContext.currentGeom,
};
const simpleLineSymbol = {
type: "simple-line",
color: [0, 230, 250],
width: 4,
};
const polylineGraphic = new Graphic({
geometry: polyline,
symbol: simpleLineSymbol,
});
// Clear previously added lines (if that's what you want)
graphicsLayer.removeAll()
graphicsLayer.add(polylineGraphic);
}, [dbPageContext.currentGeom]);
return (
<div>
<div className="webmap" ref={mapRef} />
</div>
);
};
export default MapComp;

Assigning ref in react-konva

How do we assign ref to the stage or layer object. I am using react-konva. When I do console.log(stageE1), it says undefined.
useEffect(() => {
var stage = new Konva.Stage({
container: 'stage',
width: window.innerWidth,
height: window.innerHeight,
ref: stageEl, // not working
onMouseDown: (e) => {
// deselect when clicked on empty area
const clickedOnEmpty = e.target === e.target.getStage()
if (clickedOnEmpty) {
selectShape(null)
}
},
})
stage.container().style.border = '1px solid grey'
var layer = new Konva.Layer({
ref: layerEl, // not working
})
stage.add(layer)
}, [])
This is not react-konva usage. You are using Konva API directly. If you do this, you probably don't need to use refs. But if you really want:
var layer = new Konva.Layer();
// set ref
layerEl.current = layer;
If you use react-konva, then you should define components in React way:
import { Stage, Layer } from 'react-konva';
const App = () => {
const layerEl = React.useRef();
return <Stage><Layer ref={layerEl} /></Stage>;
};

React using fetch returns undefined until save

new to react so I am not quite sure what I am doing wrong here... I am trying to call data from an API, then use this data to populate a charts.js based component. When I cmd + s, the API data is called in the console, but if I refresh I get 'Undefined'.
I know I am missing some key understanding about the useEffect hook here, but i just cant figure it out? All I want is to be able to access the array data in my component, so I can push the required values to an array... ive commented out my attempt at the for loop too..
Any advice would be greatly appreciated! My not so functional code below:
import React, {useState, useEffect} from 'react'
import {Pie} from 'react-chartjs-2'
const Piegraph = () => {
const [chartData, setChartData] = useState();
const [apiValue, setApiValue] = useState();
useEffect(async() => {
const response = await fetch('https://api.spacexdata.com/v4/launches/past');
const data = await response.json();
const item = data.results;
setApiValue(item);
chart();
},[]);
const chart = () => {
console.log(apiValue);
const success = [];
const failure = [];
// for(var i = 0; i < apiValue.length; i++){
// if(apiValue[i].success === true){
// success.push("success");
// } else if (apiValue[i].success === false){
// failure.push("failure");
// }
// }
var chartSuccess = success.length;
var chartFail = failure.length;
setChartData({
labels: ['Success', 'Fail'],
datasets: [
{
label: 'Space X Launch Statistics',
data: [chartSuccess, chartFail],
backgroundColor: ['rgba(75,192,192,0.6)'],
borderWidth: 4
}
]
})
}
return (
<div className="chart_item" >
<Pie data={chartData} />
</div>
);
}
export default Piegraph;
There are a couple issues that need sorting out here. First, you can't pass an async function directly to the useEffect hook. Instead, define the async function inside the hook's callback and call it immediately.
Next, chartData is entirely derived from the apiCall, so you can make that derived rather than being its own state variable.
import React, { useState, useEffect } from "react";
import { Pie } from "react-chartjs-2";
const Piegraph = () => {
const [apiValue, setApiValue] = useState([]);
useEffect(() => {
async function loadData() {
const response = await fetch(
"https://api.spacexdata.com/v4/launches/past"
);
const data = await response.json();
const item = data.results;
setApiValue(item);
}
loadData();
}, []);
const success = apiValue.filter((v) => v.success);
const failure = apiValue.filter((v) => !v.success);
const chartSuccess = success.length;
const chartFail = failure.length;
const chartData = {
labels: ["Success", "Fail"],
datasets: [
{
label: "Space X Launch Statistics",
data: [chartSuccess, chartFail],
backgroundColor: ["rgba(75,192,192,0.6)"],
borderWidth: 4,
},
],
};
return (
<div className="chart_item">
<Pie data={chartData} />
</div>
);
};
export default Piegraph;
pull your chart algorithm outside or send item in. Like this
useEffect(async() => {
...
// everything is good here
chart(item)
})
you might wonder why I need to send it in. Because inside useEffect, your apiValue isn't updated to the new value yet.
And if you put the console.log outside of chart().
console.log(apiData)
const chart = () => {
}
you'll get the value to be latest :) amazing ?
A quick explanation is that, the Piegraph is called whenever a state is updated. But this update happens a bit late in the next cycle. So the value won't be latest within useEffect.

Show Info bubble when clicking on a Marker in HERE Maps + REACT

So I'm currently developing a map-based application using React and HERE maps. I'm using the boilerplate in the documentation using Hooks. I'm firstly fetching the events and then displaying them in the useEffectLayout() hook, where the map loads.
import Paper from '#material-ui/core/Paper';
import useWindow from '../../CustomHooks/GetWindowSize/getSize';
import SearchBar from '../SearchBar/Search';
import {connect} from 'react-redux';
import {getEvents} from '../../actions/UserActions';
const HEREmap = ({userLocation, posts}) => {
const mapRef = React.useRef(null);
const size = useWindow();
//this is the method to add the marker to the map
const addEventsToMap = (events, H, hMap, ui) =>{
let markers = [];
events.map((el)=>{
var icon = new H.map.DomIcon(svgMarkup),
coords = {lat: el.Latitude, lng: el.Longitude},
marker = new H.map.DomMarker(coords, {icon: icon});
hMap.addObject(marker);
})
}
React.useLayoutEffect(() => {
if (!mapRef.current) return;
const H = window.H;
const platform = new H.service.Platform({
apikey: `${process.env.REACT_APP_API_KEY}`,
app_id: "XXXXXX"
});
const defaultLayers = platform.createDefaultLayers();
const hMap = new H.Map(mapRef.current, defaultLayers.vector.normal.map, {
center: { lat:userLocation.lat, lng: userLocation.lgn},
zoom: 13,
pixelRatio: window.devicePixelRatio || 1
});
//this add the user's location as a marker on the map
var icon = new H.map.DomIcon(svgMarkup),
coords = {lat: userLocation.lat, lng: userLocation.lgn},
marker = new H.map.DomMarker(coords, {icon: icon});
hMap.addObject(marker);
const behavior = new H.mapevents.Behavior(new H.mapevents.MapEvents(hMap));
const ui = H.ui.UI.createDefault(hMap, defaultLayers);
//this method gets called with the fetched events
addEventsToMap(posts, H, hMap, ui);
return () => {
hMap.dispose();
};
}, [mapRef]);
return (
<div className="map" ref={mapRef} style={{ height: size.height/1.5}}>
</div>
)
}
const mapStateToProps = state =>({
userA:state.userA
})
export default connect(mapStateToProps, {getEvents})(HEREmap);
I've read the documentation and it says to attach an onClick listener to the icon when it's created, but how do I add the info bubble to the same icon, when I need the reference to the ui as well as the information for each event?
Is there a more effective way to do it?
I'm not a React user, but I'd make the ui object available to your entire function, or the same scope as your map object. Does that help at all?

Resources