Blank screen in react-google-maps streetview - reactjs

About 50% of the time, the StreetViewPanorama shows up as a blank screen depending on the coordinates. Is there a way to check to see if the screen will show up blank before I decide to show the street view? If it will, then I would just like to show the regular map
const StreetView = withScriptjs(
withGoogleMap(props => {
const { coordinates, address, city, state, zip } = props;
return (
<GoogleMap
defaultZoom={14}
defaultCenter={{
lat: coordinates[1],
lng: coordinates[0],
}}
>
<StreetViewPanorama
defaultPosition={{
lat: coordinates[1],
lng: coordinates[0],
}}
visible
/>
</GoogleMap>
);
}),
);
export default props => {
return (
<StreetView
{...props}
googleMapURL={`https://maps.googleapis.com/maps/api/js?key=${GOOGLE_API_KEY}&libraries=visualization`}
loadingElement={<div style={{ height: `100%` }} />}
containerElement={<div style={{ height: `800px` }} />}
mapElement={<div style={{ height: `100%` }} />}
/>
);
};

Google has an endpoint to check for valid coordinates. You can use a ternary to check the status and render a marker if the Street View doesn't exist.
const StreetView = withScriptjs(
withGoogleMap(props => {
const { coordinates, address, city, state, zip } = props;
const [streetView, setStreetView] = useState(null);
axios
.get(
`https://maps.googleapis.com/maps/api/streetview/metadata?key=${GOOGLE_API_KEY}&location=${
coordinates[1]
},${coordinates[0]}`,
)
.then(resp => setStreetView(resp.data.status));
return (
<GoogleMap
defaultZoom={14}
defaultCenter={{
lat: coordinates[1],
lng: coordinates[0],
}}
>
{streetView === 'OK' ? (
<StreetViewPanorama
defaultPosition={{
lat: coordinates[1],
lng: coordinates[0],
}}
visible
/>
) : (
<></>
)}
</GoogleMap>
);
}),
);
export default props => {
return (
<StreetView
{...props}
googleMapURL={`https://maps.googleapis.com/maps/api/js?key=${GOOGLE_API_KEY}&libraries=visualization`}
loadingElement={<div style={{ height: `100%` }} />}
containerElement={<div style={{ height: `800px` }} />}
mapElement={<div style={{ height: `100%` }} />}
/>
);
};

Related

react-google-maps calls empty InfoWindow

I have problem with first call InfoWindow, it calling like 2 times and one have not any text/info and the second infoWindow have correct my info (number 2 on-screen). If I will click to another my Markeк this empty InfoWindow will stay in the first place. But if I will try to close the empty window and open any my marker this empty window will shows again in a new place.
my code:
function MapCreator() {
const [selectedPoint, setselectedPoint] = useState(null);
const [data,setData] = useState([]);
useEffect(() => {
axios.get('api/coordinates')
.then(values=>{
console.log(values.data);
setData(values.data);
})
const listener = e => {
if (e.key === "Escape") {
setselectedPoint(null);
}
};
window.addEventListener("keydown", listener);
return () => {
window.removeEventListener("keydown", listener);
};
}, []);
return (
<GoogleMap
defaultZoom={14}
defaultCenter={{ lat: 50.444571, lng: 30.559099 }}
>
{data.map(park => (
<Marker
key={park._id}
position={{
lat: park.coordinates.latitude,
lng: park.coordinates.longitude
}}
onClick={() => {
setselectedPoint(park);
}}
icon={{
url: nfcIcon,
scaledSize: new window.google.maps.Size(60, 60)
}}
/>
))}
{selectedPoint && (
<InfoWindow
onCloseClick={() => {
setselectedPoint(null);
}}
position={{
lat: selectedPoint.coordinates.latitude,
lng: selectedPoint.coordinates.longitude
}}
>
<div>
<h2>Device ID: {selectedPoint.identificatorNFC}</h2>
<p>Date: {new Date(selectedPoint.date) .toUTCString()}</p>
</div>
</InfoWindow>
)}
</GoogleMap>
);
}
const MapWrapped = withScriptjs(withGoogleMap(MapCreator));
export default function App() {
return (
<div style={{ width: `100%`, height: "100vh" }}>
<MapWrapped
googleMapURL={`https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=geometry,drawing,places&key=${
keys.googleApi
}`}
loadingElement={<div style={{ height: `100%` }} />}
containerElement={<div style={{ height: `100%` }} />}
mapElement={<div style={{ height: `100%` }} />}
/>
</div>
);
}
Tbh, I don't see any kind of problem in your code but I suggest try this out:
function MapCreator() {
const [selectedPoint, setselectedPoint] = useState(null);
const [data,setData] = useState([]);
useEffect(() => {
axios.get('api/coordinates')
.then(values=>{
console.log(values.data);
setData(values.data);
})
const listener = e => {
if (e.key === "Escape") {
setselectedPoint(null);
}
};
window.addEventListener("keydown", listener);
return () => {
window.removeEventListener("keydown", listener);
};
}, []);
return (
<GoogleMap
defaultZoom={14}
defaultCenter={{ lat: 50.444571, lng: 30.559099 }}
>
{data.map(park => (
<Marker
key={park._id}
position={{
lat: park.coordinates.latitude,
lng: park.coordinates.longitude
}}
onClick={() => {
setselectedPoint(park);
}}
icon={{
url: nfcIcon,
scaledSize: new window.google.maps.Size(60, 60)
}}
>
{selectedPoint && selectedPoint._id === park._id && (
<InfoWindow onCloseClick={() => setselectedPoint(null)}
>
<div>
<h2>Device ID: {selectedPoint.identificatorNFC}</h2>
<p>Date: {new Date(selectedPoint.date) .toUTCString()}</p>
</div>
</InfoWindow>
)}
</Marker>
))}
</GoogleMap>
);
}
const MapWrapped = withScriptjs(withGoogleMap(MapCreator));
export default function App() {
return (
<div style={{ width: `100%`, height: "100vh" }}>
<MapWrapped
googleMapURL={`https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=geometry,drawing,places&key=${
keys.googleApi
}`}
loadingElement={<div style={{ height: `100%` }} />}
containerElement={<div style={{ height: `100%` }} />}
mapElement={<div style={{ height: `100%` }} />}
/>
</div>
);
}

react-google-maps map refreshes after onclick

I'm using react-google-maps in a Map component and whenever I click on a marker two odd things happen. First, there is two InfoWindow's opening, one blank one and one with my div. Also, whenever an onclick is performed the map refreshes which is not what I want. I am calling my Map component from App.js.
import React, { useState, Component } from'react';
import { GoogleMap, withScriptjs, withGoogleMap, Marker, InfoWindow } from "react-google-maps";
function Map(props) {
const WrappedMap = withScriptjs(withGoogleMap(CreateMap))
const [selectedPatio, setSelectedPatio] = useState(null)
function CreateMap(){
return (
<GoogleMap
defaultZoom={13}
defaultCenter={{ lat: 49.278352, lng: -123.122538 }}
>
{props.patios.map((patio) => (
<Marker
key={patio.name}
position={{
lat: patio.lat,
lng: patio.lng}}
onClick={() => {
setSelectedPatio(patio);
}}
/>
))}
{selectedPatio && (
<InfoWindow
onCloseClick={() => {
setSelectedPatio(null);
}}
position={{
lat: selectedPatio.lat,
lng: selectedPatio.lng
}}
>
<div>
asd
</div>
</InfoWindow>
)}
</GoogleMap>)
}
return (
<WrappedMap
googleMapURL={'https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=gemotry,drawing,places&key=XXX'}
loadingElement={<div style={{ height: `100%` }} />}
containerElement={<div style={{ height: `100%` }} />}
mapElement={<div style={{ height: `100%` }} />}
/>
);
}
export default Map
//This is what my render looks like in app.js where i'm calling Map and sending an array of patios to props
render() {
return (
<BrowserRouter>
<NavBar data={{ icon:"location", text1:"Map", text2:"About"}}></NavBar>
<div style={{ width: `100vw` , height: `75vh`, maxWidth: `100%` }}>
<Map patios={this.state.patios}/>
<div>
<PatioMasonry patios={this.state.patios}/>
</div>
</div>
<div>
<BottomNavBar/>
</div>
<div>
<Switch>
<Route path="/" component={Homescreen} exact/>
</Switch>
</div>
</BrowserRouter>
);
}
}
You are defining a functional component inside another functional component. By doing this, when the parent component re-renders, then a new instance of child component is created and the component is re-mounted instead of re-render. Therefore your map is getting refreshed.
Move your CreateMap component outside of Map component
import React, { useState, Component } from'react';
import { GoogleMap, withScriptjs, withGoogleMap, Marker, InfoWindow } from "react-google-maps";
const WrappedMap = withScriptjs(withGoogleMap(CreateMap))
function CreateMap(){
const [selectedPatio, setSelectedPatio] = useState(null)
return (
<GoogleMap
defaultZoom={13}
defaultCenter={{ lat: 49.278352, lng: -123.122538 }}
>
{props.patios.map((patio) => (
<Marker
key={patio.name}
position={{
lat: patio.lat,
lng: patio.lng}}
onClick={() => {
setSelectedPatio(patio);
}}
/>
))}
{selectedPatio && (
<InfoWindow
onCloseClick={() => {
setSelectedPatio(null);
}}
position={{
lat: selectedPatio.lat,
lng: selectedPatio.lng
}}
>
<div>
asd
</div>
</InfoWindow>
)}
</GoogleMap>)
}
function Map(props) {
return (
<WrappedMap
googleMapURL={'https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=gemotry,drawing,places&key=XXX'}
loadingElement={<div style={{ height: `100%` }} />}
containerElement={<div style={{ height: `100%` }} />}
mapElement={<div style={{ height: `100%` }} />}
/>
);
}
export default Map

Access variable outside render

I'm having a problem in my code. I already can make a marker on the map with lat and lng. But I want to display a simple span with the coordinates under the map. I try to access this.props.markerPosition and it's null in render.
What is the issue here?
https://stackblitz.com/edit/react-snxake
const WrappedMap = compose(
withStateHandlers(() => ({
isMarkerShown: false,
markerPosition: null
}), {
onMapClick: ({ isMarkerShown }) => (e) => ({
markerPosition: e.latLng,
isMarkerShown:true
})
}),
withScriptjs,
withGoogleMap
)
(props =>
<GoogleMap
defaultZoom={8}
defaultCenter={{ lat: -34.397, lng: 150.644 }}
onClick={props.onMapClick}
>
{props.isMarkerShown && <Marker position={props.markerPosition} onClick={props.onMarkerClick} defaultOptions={{ styles: mapStyles}} />}
</GoogleMap>
)
export default class ParkingSpotsSettings extends React.Component {
state = {
evaluationExecuted: false,
evaluation: false
};
constructor() {
super();
this.state = {
coordinates: [],
title: '',
description: '',
capacity: 0
}
}
componentDidMount() { }
render() {
return (
<div className="App">
<Navigation />
<div className="container-fluid">
<div className="row">
<div className="col-md-6" style={{ width: "100vw", height: "40vh" }}>
<WrappedMap googleMapURL={`https://maps.googleapis.com/maps/api/js?key=v=3.exp&libraries=geometry,drawing,places`}
loadingElement={<div style={{ height: "100%" }} />}
containerElement={<div style={{ height: "100%" }} />}
mapElement={<div style={{ height: "100%" }} />}
/>
</div>
<span>Coordinates are: {this.props.markerPosition}</span>
</div>
</div>
</div >
);
}
}
Your prop is called position not markerPosition. So you need to use this.props.position.

How to pass data from a parent component or use axios here in the map function for react-google-maps library?

I try to pass an array of the markers' coordinates and some other props from the index page (parent of the CardTransactionMapRGMs component) to the map function, so it can use the data to map the Markers. However, I can get the props in the CardTransactionMapRGMs, but I don't know how to get it in the Map function or how to reorganize it.
Also I'm quite confused about this "const WrapperMap = withScriptjs(withGoogleMap(Map));"
Thank you so much! Here's my code:
in index.js
<CardTransactionMapRGMs charges={this.state.charges} coordinates={this.state.coordinates} />
in CardTransactionMapRGMs.js
import React, { Component } from 'react';
import axios from 'axios';
import { GoogleMap, Marker, withScriptjs, withGoogleMap } from "react-google-maps";
import Constants from '../Constants';
import MapMarker from './MapMarker';
function Map() {
return (
<GoogleMap
defaultZoom={10}
defaultCenter={{ lat: 38.96, lng: -77.29 }}
>
//I want to use {props.coordinates.map(e)=> {
// <Marker...>}}here
<Marker position={{ lat: 38.96, lng: -77.29 }} />
</GoogleMap>
)
}
class CardTransactionMapRGMs extends Component {
render() {
const WrapperMap = withScriptjs(withGoogleMap(Map));
return (
<div>
<WrapperMap
googleMapURL={`https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=geometry,drawing,places&key=${Constants.GOOGLE_MAP_API_KEY}`}
loadingElement={<div style={{ height: '100%' }}></div>}
containerElement={<div style={{ height: `400px` }} />}
mapElement={<div style={{ height: `100%` }} />}
/>
</div>
);
}
}
export default CardTransactionMapRGMs;
You can just use your props in your Map functional component.
function Map(props){
return <GoogleMap
defaultZoom={10}
defaultCenter={{ lat: 38.96, lng: -77.29 }}>
{props.coordinates.map(markerProps)=> <Marker {markerProps}>}
<Marker position={{ lat: 38.96, lng: -77.29 }} />
</GoogleMap>
}
CardTransactionMapRGMs.js
class CardTransactionMapRGMs extends Component {
render() {
const WrapperMap = withScriptjs(withGoogleMap(Map));
return (
<div>
<WrapperMap
googleMapURL={`https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=geometry,drawing,places&key=${Constants.GOOGLE_MAP_API_KEY}`}
loadingElement={<div style={{ height: '100%' }}></div>}
containerElement={<div style={{ height: `400px` }} />}
mapElement={<div style={{ height: `100%` }} />}
coordinates={[{ lat: 38.96, lng: -77.29 }]}
/>
</div>
);
}
}

geolocation in React, use react-google-maps

How to change defaultCenter in react-google-maps ?
I need to find my geolocation and change default values lat and lng.
import React from "react";
import { withScriptjs, withGoogleMap, GoogleMap, Marker } from "react-google-maps";
const getLocation = () =>{
const pos = {};
const geolocation = navigator.geolocation;
if (geolocation) {
geolocation.getCurrentPosition(findLocal, showEror);
}
function findLocal(position){
pos.lat = position.coords.latitude;
pos.lng = position.coords.longitude;
}
function showEror(){console.log(Error)}
return pos;
};
const myLocation = getLocation(); // object has lat and lng
I need to transfer my data to the component MapWithAMarker next: Ğ¡enter={myLocation} and Marker position={myLocation}
class GoogleMapCenter extends React.Component{
render(){
const MapWithAMarker = withScriptjs(withGoogleMap(props =>
<GoogleMap
defaultZoom={10}
defaultCenter={{ lat: -34.397, lng: 150.644 }}>
{props.isMarkerShown && <Marker position={{ lat: -34.397, lng: 150.644 }} />}
</GoogleMap>
));
return(
<MapWithAMarker
isMarkerShown
googleMapURL="https://maps.googleapis.com/maps/api/js?key=AIzaSyC4R6AN7SmujjPUIGKdyao2Kqitzr1kiRg&v=3.exp"
loadingElement={<div style={{ height: `100%` }} />}
containerElement={<div style={{ height: `400px` }} />}
mapElement={<div style={{ height: `100%` }} />}
/>
)
}
}
export default GoogleMapCenter;
If I use this.props, it does not work.
<MapWithAMarker
center={this.props.myLocation}
position={this.props.myLocation}
isMarkerShown
googleMapURL="https://maps.googleapis.com/maps/api/js?key=AIzaSyC4R6AN7SmujjPUIGKdyao2Kqitzr1kiRg&v=3.exp"
loadingElement={<div style={{ height: `100%` }} />}
containerElement={<div style={{ height: `400px` }} />}
mapElement={<div style={{ height: `100%` }} />}
/>
or
<GoogleMap
defaultZoom={10}
defaultCenter={this.props.myLocation}>
{props.isMarkerShown && <Marker position={this.props.myLocation} />}
</GoogleMap>
Default properties like defaultCenter could only be set as initial state, center property could be used instead to re-render (center) the map.
The following example demonstrates how to center the map based on current location
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
currentLatLng: {
lat: 0,
lng: 0
},
isMarkerShown: false
}
}
showCurrentLocation = () => {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
position => {
this.setState(prevState => ({
currentLatLng: {
...prevState.currentLatLng,
lat: position.coords.latitude,
lng: position.coords.longitude
},
isMarkerShown: true
}))
}
)
} else {
error => console.log(error)
}
}
componentDidMount() {
this.showCurrentLocation()
}
render() {
return (
<div>
<MapWithAMarker
isMarkerShown={this.state.isMarkerShown}
currentLocation={this.state.currentLatLng} />
</div>
);
}
}
where
const MapWithAMarker = compose(
withProps({
googleMapURL: "https://maps.googleapis.com/maps/api/js",
loadingElement: <div style={{ height: `100%` }} />,
containerElement: <div style={{ height: `400px` }} />,
mapElement: <div style={{ height: `100%` }} />,
}),
withScriptjs,
withGoogleMap
)((props) =>
<GoogleMap
defaultZoom={8}
center={{ lat: props.currentLocation.lat, lng: props.currentLocation.lng }}
>
{props.isMarkerShown && <Marker position={{ lat: props.currentLocation.lat, lng: props.currentLocation.lng }} onClick={props.onMarkerClick} />}
</GoogleMap>
)
Demo (edit)

Resources