Unable to render the Google map on state change - reactjs

I am trying to change the state of salesPropertyInfoWindowIn by assigning an
array salesPropertyInfoWindowOut that is defined globally.
initial value of
salesPropertyInfoWindowIn :
[false,false,false,false,false,false,false,false,false,false]
onMarkerClick method changes the value of index passed as an parameter then assigns the value in salesPropertyInfoWindowIn. However, this doesn't rerender the map. Please help me by suggesting some solution.
const MapWithAMarkerClusterer = compose(
withProps({
googleMapURL:
"https://maps.googleapis.com/maps/api/js?key=AIzaSyDlMypBHZKOOgwp7PBHrQSvf75Y1sM2gnU&v=3.exp&libraries=geometry,drawing,places",
loadingElement: <div style={{ height: `100%` }} />,
containerElement: <div style={{ height: `390px` }} />,
mapElement: <div style={{ height: `100%` }} />
}),
withStateHandlers(
() => ({
salesPropertyInfoWindowIn: salesPropertyInfoWindowOut,
isOpen: false,
}),
{
onToggleOpen: ({isOpen}) => () => ({
isOpen: !isOpen
}),
onMarkerClick: ({salesPropertyInfoWindowIn}) => (marker, i) => (
salesPropertyInfoWindowOut[i] = !salesPropertyInfoWindowOut[i],
{salesPropertyInfoWindowIn: salesPropertyInfoWindowOut}
)
}),
withScriptjs,
withGoogleMap)(props => (
<GoogleMap
defaultZoom={15}
defaultCenter={
home.currentProperty != null
? {
lat: parseFloat(home.currentProperty.property.location.lat),
lng: parseFloat(home.currentProperty.property.location.lon)
}
: ""
}
>
<MarkerClusterer averageCenter enableRetinaIcons gridSize={10}>
{home.propSalesData != undefined || home.propSalesData != null
? props.markers.map((marker, i) => (
<Marker
icon={salesPropertyMarkerImage}
onClick={() => props.onMarkerClick(marker, i)}
key={i}
position={{
lat: parseFloat(marker.location.lat),
lng: parseFloat(marker.location.lon)
}}
>
{(props.salesPropertyInfoWindowIn[i] == true) ?
(console.log('Inside', props.salesPropertyInfoWindowIn[i]),
<InfoWindow>
<text>
{home.propSalesData[i].agent.name != undefined ||
home.propSalesData[i].agent.name != null
? "Agent: " + home.propSalesData[i].agent.name
: "Purchaser: " +
home.propSalesData[i].saleParticipants
.purchasersSummary}
</text>
</InfoWindow>
) : ""}
</Marker>
))
: ""}

You can try storing the index of the clicked marker, instead of using the 2 arrays salesPropertyInfoWindowIn / salesPropertyInfoWindowOut.
onMarkerClick(index) {
this.setState({clickedMarkerIndex: index})
}
Then, to render InfoWindows only on clicked markers:
{props.markers.map((marker, index) => {
<Marker onClick={() => props.onMarkerClick(index)}>
{props.clickedMarkerIndex === index &&
<InfoWindow> etc etc
}
</Marker>
})

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>
);
}

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.

Blank screen in react-google-maps streetview

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%` }} />}
/>
);
};

How I can put on dynamic markers on react-google-maps when I click on a certain part of the map?

I'm trying to put marker when I click on map. react-google-maps documentation is not good and I feel confused.
class Map extends Component {
render() {
const GoogleMapExample = withGoogleMap(props => (
<GoogleMap
center={{ lat: this.props.latitude, lng: this.props.longitude }}
zoom={13}
>
{this.props.markers.map(marker => {
return <SkateMarker key={marker.title} marker={marker} />;
})}
</GoogleMap>
));
return (
<div>
<GoogleMapExample
containerElement={
<div style={{ height: `500px`, width: "1000px" }} />
}
mapElement={<div style={{ height: `100%` }} />}
/>
</div>
);
}
}
export default Map;
The following example demonstrates how to add a marker on map click using react-google-maps:
class MapWithMarkers extends React.Component {
state = {
places: []
};
addMarker(e) {
const newPlace = { id: this.state.places.length, lat: e.latLng.lat(), lng: e.latLng.lng() };
this.setState({
places: [...this.state.places,newPlace]
})
}
render() {
return (
<GoogleMap
onClick={this.addMarker.bind(this)}
defaultZoom={this.props.zoom}
defaultCenter={this.props.center}
>
{this.state.places.map(place => {
return (
<Marker
key={place.id}
position={{ lat: place.lat, lng: place.lng }}
/>
);
})}
</GoogleMap>
);
}
}
Demo

Display only one InfoWindow

I realise this has been asked before, however, I'm unable to figure out what I'm doing wrong here. I have a map that displays multiple markers and when I click on a marker it is supposed to displays the InfoWindow about that marker. The problem that when I click on a marker, all the InfoWindow boxes pop up instead of just the one I've clicked on.
const MapWithAMarkerClusterer = compose(
withProps({
googleMapURL: "MY KEY",
loadingElement: <div style={{ height: `100%` }} />,
containerElement: <div style={{ height: `400px` }} />,
mapElement: <div style={{ height: `100%` }} />,
}),
withHandlers({
onMarkerClustererClick: () => (markerClusterer) => {
const clickedMarkers = markerClusterer.getMarkers()
}
}),
withStateHandlers(() => ({
isOpen: false,
markerId: ''
}), {
onToggleOpen: ({ isOpen }) => (markerId) => ({
isOpen: !isOpen,
markerId: markerId
})
}),
withScriptjs,
withGoogleMap
)(props =>
<GoogleMap
defaultZoom={4}
defaultCenter={{ lat: -23.696248, lng: 133.880731 }}
>
<MarkerClusterer
onClick={props.onMarkerClustererClick}
averageCenter
enableRetinaIcons
gridSize={60}
>
{props.companies.map(company => (
<span key={company.company_name}>
<Marker
position={company.google_maps.geometry_location}
onClick={() => props.onToggleOpen(company.company_name)}
>
{props.isOpen[props.markerId] && <InfoWindow onCloseClick={props.onToggleOpen}>
<p>Test</p>
</InfoWindow>}
</Marker>
</span>
))}
</MarkerClusterer>
</GoogleMap>
);
Ok, this was a silly mistake. I've updated my code below and it works.
{props.isOpen && (props.markerId == company.company_name) && <InfoWindow onCloseClick={props.onToggleOpen}>
<p>Test</p>
</InfoWindow>}

Resources