How to add custom controls on google map? - reactjs

I am using google-maps-react library and i want to add cutom controls on google map like buttons, input elements etc. plaese see image i want like this.

google-map-react is a component written over a small set of the Google Maps API. It allows you to render any React component on the Google Map. It is fully isomorphic and can render on a server. Additionally, it can render map components in the browser even if the Google Maps API is not loaded. It uses an internal, tweakable hover algorithm - every object on the map can be hovered.
In the simple case you just need to add lat and lng props to any child of GoogleMapReact component.
import GoogleMapReact from 'google-map-react';
const AnyReactComponent = ({ text }) => <div>{text}</div>;
class SimpleMap extends Component {
static defaultProps = {
center: {
lat: 59.95,
lng: 30.33
},
zoom: 11
};
render() {
return (
// Important! Always set the container height explicitly
<div style={{ height: '100vh', width: '100%' }}>
<GoogleMapReact
bootstrapURLKeys={{ key: /* YOUR KEY HERE */ }}
defaultCenter={this.props.center}
defaultZoom={this.props.zoom}
>
<AnyReactComponent
lat={59.955413}
lng={30.337844}
text="My Marker"
/>
</GoogleMapReact>
</div>
);
}
}
export default SimpleMap;

Related

google-maps-react Map not showing up

I'm working on an app where I'd like to display a google maps with a marker. I thought I followed the steps correctly on the google-maps-react documentation, but I'm having issues.
First, the map shows up gray and none of the land/ocean is showing.
Second, the map seems to go off the screen but my browser doesn't scroll so I can't see the rest of the map. I'm assuming this has to do with the styling but I can't figure it out.
Here is a screenshot of the browser for reference:
My Map component:
import React, { Component } from 'react';
import { Map, GoogleApiWrapper, Marker } from 'google-maps-react';
const mapStyles = {
width: '100%',
height: '90%',
};
export class MapContainer extends Component {
state = {
showingInfoWindow: false, // Hides or shows the InfoWindow
activeMarker: {}, // Shows the active marker upon click
selectedPlace: {} // Shows the InfoWindow to the selected place upon a marker
};
render() {
const {google, location} = this.props;
return (
<Map
google={this.props.google}
zoom={5}
style={mapStyles}
initialCenter={{
lat: location.latitude,
lng: location.longitude
}}
center={{
lat: location.latitude,
lng: location.longitude
}}
>
<Marker
name={'ISS'}
position={{
lat: location.latitude,
lng: location.longitude
}}
icon={{
url: 'https://icons.iconarchive.com/icons/goodstuff-no-nonsense/free-space/512/international-space-station-icon.png',
anchor: new google.maps.Point(32,32),
scaledSize: new google.maps.Size(80,80)
}}
/>
</Map>
);
}
}
export default GoogleApiWrapper({
apiKey:process.env.REACT_APP_API_KEY
})(MapContainer);
Any help would be appreciated
I was actually able to solve the issue by adding the styling: 'overflow: visible' to my map component. I'm not sure why this was an issue or why it defaults to hidden, so if anyone has insight on that it would be helpful. But this solved both issues I was having.

Is this the correct usage of React Components?

I am new to React. I want to share my components files with you. The code is syntactically correct and executes just fine. I just want to know, if its logically correct and the correct use of concepts such as states.
Is it correct to save lng and lat coords from the GeoLocation API to the MapContainer State?
Is it the correct use of ComponentDidMount() function.
What other ways can I improve the code.
// Map.js
import React from 'react'
import 'bootstrap/dist/css/bootstrap.css';
import GoogleMapReact from 'google-map-react';
function Map(props) {
const screenHeight = window.screen.height;
return (
<div style={{ height: screenHeight - 250 }}>
<GoogleMapReact
bootstrapURLKeys={{ key: "123mykey" }}
center={props.center}
defaultZoom={props.zoom}
></GoogleMapReact>
</div>
);
}
Map.defaultProps = {
center: {
lat: 59.95,
lng: 30.33
},
zoom: 11
};
export default Map
// MapContainer.js
import React from 'react'
import 'bootstrap/dist/css/bootstrap.css';
import Map from './Map'
class MapContainer extends React.Component {
constructor(props) {
super(props);
this.state = {
center: {
lat: 0, lng: 0
}
}
this.getLocation = this.getLocation.bind(this);
this.showPosition = this.showPosition.bind(this);
}
getLocation() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(this.showPosition);
} else {
console.log("Geolocation is not supported by this browser.");
}
}
showPosition(position) {
this.setState({
center: {
lat: position.coords.latitude,
lng: position.coords.longitude
}
});
}
componentDidMount() {
this.getLocation();
}
render() {
return (
<div className="row">
<div className="col-md-9">
<Map center={this.state.center} />
</div>
<div className="col-md-3 d-sm-none d-md-block d-none d-sm-block">
<h1>Menu</h1>
</div>
</div>
);
}
}
export default MapContainer
Looks fine to me. You only need to import 'bootstrap/dist/css/bootstrap.css'; in your main index.js file.
Everything seems good, you are doing right
Is it correct to save lng and lat coords from the GeoLocation API to the MapContainer State?
Is it the correct use of ComponentDidMount() function?
Yeah, Why not ?
What other ways can I improve the code.
there are some minor changes like:
1- you can import Component on top and the class definition would be smaller
2- it is a good practice to use arrow function component definition like this
export default (props) => {
const screenHeight = window.screen.height;
return (
<div style={{ height: screenHeight - 250 }}>
<GoogleMapReact
bootstrapURLKeys={{ key: "AIzaSyCV1fQD2VC6HoNbuuSPkE0q_QZvDf117PY" }}
center={props.center}
defaultZoom={props.zoom}
></GoogleMapReact>
</div>
);
}
generally you are using react in right way, keep going
It looks fine at MapContainer (Example 2) but I propose separate your view based logics and the others. For example, the getLocation function is not based on your view (not depending React component or changing the view) so we can plug out this logic function into an independent function later the showPosition function is going to use that function.

Difference between google-map-react and google-maps-react?

While i'm using Google maps in reactjs, I found two different npms like google-map-react and google-maps-react. As i'm beginner of react i'm bit confused what to use(prefer). Although I found this link but it is bit different which is about- Difference between google-map-react and react-google-maps
The following is the sample code for google-map-react
import React, { Component } from 'react';
import GoogleMapReact from 'google-map-react';
const AnyReactComponent = ({ text }) => <div>{text}</div>;
class SimpleMap extends Component {
static defaultProps = {
center: {
lat: 59.95,
lng: 30.33
},
zoom: 11
};
render() {
return (
// Important! Always set the container height explicitly
<div style={{ height: '100vh', width: '100%' }}>
<GoogleMapReact
bootstrapURLKeys={{ key: /* YOUR KEY HERE */ }}
defaultCenter={this.props.center}
defaultZoom={this.props.zoom}
>
<AnyReactComponent
lat={59.955413}
lng={30.337844}
text="My Marker"
/>
</GoogleMapReact>
</div>
);
}
}
export default SimpleMap;
The following is the sample code for google-maps-react
import React, { Component } from "react";
import { Map, GoogleApiWrapper, Marker } from "google-maps-react";
const mapStyles = {
width: "100%",
height: "100%"
};
class MapContainer extends Component {
constructor(props) {
super(props);
this.state = {
stores: [
{ lat: 47.49855629475769, lng: -122.14184416996333 },
{ latitude: 47.359423, longitude: -122.021071 },
{ latitude: 47.5524695, longitude: -122.0425407 }
]
};
}
displayMarkers = () => {
return this.state.stores.map((store, index) => {
return (
<Marker
key={index}
id={index}
position={{
lat: store.latitude,
lng: store.longitude
}}
onClick={() => console.log("Clicked me..!")}
/>
);
});
};
render() {
return (
<div>
<Map
google={this.props.google}
zoom={8}
style={mapStyles}
initialCenter={{ lat: 47.444, lng: -122.176 }}
>
{this.displayMarkers()}
</Map>
</div>
);
}
}
export default GoogleApiWrapper({
apiKey: "key"
})(MapContainer);
Please help me Which is optimum to use.
Thanks in advance
As far as I have figured out, google-maps-react mainly focuses on drawing geometric shapes like marker, infowindow, polyline, polygon or circle. They also offer lazy loading for the maps. I have used this library in two of my projects.
On the other hand, google-map-react renders a map where you can put a customized react component in any co-ordinate.
Both libraries can be used to implement API services like autocomplete or direction-services.
You may use any one of them according to your needs.
I wanted to use one of these packages in my project and that's where I created sample projects using both packages so I can test the performance. I wanted to plot thousands of markers and my primary requirement was performance.
I found that google-maps-react handles large markers (>= 10000) of dataset better than google-map-react. Please note for my project, I was not allowed to use clusters and all the markers should be visible all the time on the map. The clustering google-map-react works in a decent way even with larger marker datasets.
It is important to note here that the google-map-react package is updated more frequently than google-maps-react. Avg weekly downloads for google-map-react package are 185,833( 13th July 21) while for google-maps-react average weekly downloads 54,750 ( 13th July 21).
Please note for so many people plotting thousands of markers and relative performance are really important so I decided to write as a separate answer. Apologies for not writing specific performance numbers since I was in hurry.

Anchor Link under Map Component not clickable

I am writing my first React App (using create-react-app) and I wrote a Map component using google-maps-react. However, the links BELOW the map cannot be clicked.
Actually, on my webpage, this issue is present only on small and medium-sized screens, while it works perfectly on large screens (small, medium and large as defined by materializecss). I tried to reproduce the issue on a minimal working example, without materialize, just using the boilerplate code created by `npx create-react-app my-app' and adding the following:
MapComponent.js
import React from 'react';
import { Map, GoogleApiWrapper } from 'google-maps-react';
const mapStyles = {
width: '80vw',
height: '45vw',
marginLeft: 'auto',
marginRight: 'auto',
display: 'block'
};
const MapComponent = (props) => {
return (
<div className="MapComponent">
<div>
Google
</div>
<Map
google={props.google}
zoom={10}
style={mapStyles}
initialCenter={{
lat: 40,
lng: 12
}}
/>
<div>
Google
</div>
</div>
);
}
export default GoogleApiWrapper({
apiKey: "Key"
})(MapComponent);
and then in App.js:
import React, { Component } from 'react';
import MapComponent from './MapComponent';
class App extends Component {
render() {
return (
<div className="Appr">
<MapComponent />
</div>
);
}
}
export default App;
(the key is not reported in the example, so maps will display the frame with an error message, but the issue is the same with the key). The first link to google.com can be clicked and works, while the second does not. Any solution/workaround?
Finally, I went through the source code of google-maps-react and found the solution. It is very simple but rather undocumented. Apart from style the Map component accepts a containerStyle prop, allowing to change the tyle of the container wrapping Map. By default, the position is set to position: absolute giving the aforementioned behavior. The following code solves the issue for me:
import React from 'react';
import { Map, GoogleApiWrapper } from 'google-maps-react';
const mapStyles = {
width: '80vw',
height: '45vw',
marginLeft: 'auto',
marginRight: 'auto',
display: 'block'
};
const containerStyle = { {/* Added style */}
position: 'static'
}
const MapComponent = (props) => {
return (
<div className="MapComponent">
<div>
Google
</div>
<Map
google={props.google}
zoom={10}
style={mapStyles}
containerStyle={containerStyle} {/* Added prop */}
initialCenter={{
lat: 40,
lng: 12
}}
/>
<div>
Google
</div>
</div>
);
}
export default GoogleApiWrapper({
apiKey: "Key"
})(MapComponent);

Google Maps React not loading

I am showing a basic example of Google Maps React with a valid key but isntead of showing me the map it shows me a text saying "Loading map..."
import {GoogleApiWrapper, Map, MapProps} from 'google-maps-react';
import * as React from 'react'
export class MapContainer extends React.Component<MapProps> {
public render() {
return (
<Map
google={this.props.google}
centerAroundCurrentLocation={true}
zoom={20}
/>
);
}
}
export default GoogleApiWrapper({
apiKey: (API_KEY)
})(MapContainer)
There is no error in console log and anything.
First of all please make sure on the places you're including the MapContainer you're using the default export as follows:
import MapContainer from './pathToContainer/MapContainer'
Otherwise importing it via named export { MapContainer } you will skip GoogleApiWrapper HOC.
Also you may need to provide the width and height maps properties as follows:
<Map
style={{ width: '100%', height: '100%' }}
google={this.props.google}
centerAroundCurrentLocation={true}
zoom={20}
/>
Or you may need to style the map's wrapper div:
<div
style={{
position: "relative",
height: "calc(100vh - 20px)"
}}
>
<Map
google={this.props.google}
centerAroundCurrentLocation={true}
zoom={20}
/>
</div>
Here's a complete working example, taken from the docs.

Resources