ReactJS useState, onClick show InfoWindow - reactjs

In my react google maps code I am not able to set onclick open InfoWindow. I am referring to this tutorial: https://youtu.be/WZcxJGmLbSo?t=1545
my code:
import React, { useState } from "react";
import {
GoogleMap,
useLoadScript,
Marker,
InfoWindow,
} from "#react-google-maps/api"; // --> using #react package
const libraries = ["places"];
const mapContainerStyle = {
width: "100%",
height: "100vh",
};
const center = {
lat: 51.103807,
lng: 10.057477,
};
export default function App() {
const [setSState, sstate] = React.useState(null);
const { isLoaded, loadError } = useLoadScript({
googleMapsApiKey: process.env.REACT_APP_GOOGLE_KEY,
libraries,
});
if (loadError) return "error loading maps";
if (!isLoaded) return "loading maps";
return (
<div>
<GoogleMap
mapContainerStyle={mapContainerStyle}
zoom={6}
center={{ lat: 50.115509, lng: 8.690508 }}
>
<Marker
position={{ lat: 51.081753, lng: 13.696073 }}
onClick={() => {
sstate(!setSState);
console.log("marker clicked");
}}
}}
></Marker>
</GoogleMap>
</div>
);
}
I am not able to show the marker only when clicked. What shall I do? I am hard coding the data for now. I am still new to props.
And when click the X on marker and click on the marker again it crashes. I know I have to use onCloseClick which when I tried didnt work.

Have a look at the useState Hook docs.
The hook will give you a state variable to use, and a function that can be used to update that variable.
At the top of the component you want to have:
const [centerState, setCenterState] = useState(null);
and then you can use this in the Marker to update the state:
onClick={() => setCenterState(center)}
That will update the state, but in your code you are currently getting center from an object assigned outside of the component, you might want to think about what you are going to set in that state.

Related

Google Map React component loses data when placed into divs

I have a working GoogleMapReact component that takes latitude and longitude, and places markers on the map. The problem I face is I need to style the Marker component and when I place it into DIV or any other html element, all markes lose their coordinates and are just in vertical row on the map.
Here is the code:
import React, { useState } from "react";
import GoogleMapReact from "google-map-react";
import getCenter from "geolib/es/getCenter";
import Marker from "../components/Marker";
function MapMe1({ searchResults }) {
//transform the search results object into {latitude,longitude} format
const coordinates = searchResults.map((result) => ({
longitude: result.long,
latitude: result.lat,
}));
const center = getCenter(coordinates);
const [viewport, setViewport] = useState({
width: "600px",
height: "max-height: 75%",
center: { lat: center.latitude, lng: center.longitude },
zoom: 11,
});
return (
<GoogleMapReact
//mapContainerStyle={containerStyle}
bootstrapURLKeys={{ key: process.env.google_maps_key }}
{...viewport}
onViewportChange={(nextViewport) => setViewport(nextViewport)}
>
{searchResults.map((result) => (
// It works, but if I wrap this in <div> lat and lng no longer available...
<Marker
lat={result.lat}
lng={result.long}
offsetLeft={-20}
offsetTop={-10}
titles={result.title}
/>
))}
</GoogleMapReact>
);
}
export default MapMe1;
I want to style the marker to show a tooltip but for some reason is the Marker component loses all data. Why is this happening?

Change the height and width on a google map in React js

Hi guys i am working on a small presentation project. I need make a google map with the ability to auto search location. I found a code what does all that from a tutorial but i can't change the width and the height. I need it to be small, something like: height: 200px and width: 200px.
GoogleMap.js
import React, { Component } from 'react';
import {Map, Marker, GoogleApiWrapper} from 'google-maps-react';
import PlacesAutocomplete, {
geocodeByAddress,
getLatLng,
} from 'react-places-autocomplete';
export class MapContainer extends Component {
constructor(props) {
super(props);
this.state = {
// for google map places autocomplete
address: '',
showingInfoWindow: false,
activeMarker: {},
selectedPlace: {},
mapCenter: {
lat: 49.2827291,
lng: -123.1207375
}
};
}
handleChange = address => {
this.setState({ address });
};
handleSelect = address => {
this.setState({ address });
geocodeByAddress(address)
.then(results => getLatLng(results[0]))
.then(latLng => {
console.log('Success', latLng);
// update center state
this.setState({ mapCenter: latLng });
})
.catch(error => console.error('Error', error));
};
render() {
return (
<div id='googleMaps'>
<PlacesAutocomplete
value={this.state.address}
onChange={this.handleChange}
onSelect={this.handleSelect}
>
{({ getInputProps, suggestions, getSuggestionItemProps, loading }) => (
<div>
<input
{...getInputProps({
placeholder: 'Search Places ...',
className: 'location-search-input',
})}
/>
<div className="autocomplete-dropdown-container">
{loading && <div>Loading...</div>}
{suggestions.map(suggestion => {
const className = suggestion.active
? 'suggestion-item--active'
: 'suggestion-item';
// inline style for demonstration purpose
const style = suggestion.active
? { backgroundColor: '#fafafa', cursor: 'pointer' }
: { backgroundColor: '#ffffff', cursor: 'pointer' };
return (
<div
{...getSuggestionItemProps(suggestion, {
className,
style,
})}
>
<span>{suggestion.description}</span>
</div>
);
})}
</div>
</div>
)}
</PlacesAutocomplete>
<Map
google={this.props.google}
initialCenter={{
lat: this.state.mapCenter.lat,
lng: this.state.mapCenter.lng
}}
center={{
lat: this.state.mapCenter.lat,
lng: this.state.mapCenter.lng
}}
>
<Marker
position={{
lat: this.state.mapCenter.lat,
lng: this.state.mapCenter.lng
}} />
</Map>
</div>
)
}
}
export default GoogleApiWrapper({
apiKey: ('_MY_API_KEY_')
})(MapContainer)
App.js
import './App.css';
import GoogleMap from './components/GoogleMap';
function App() {
return (
<div className="App">
<h1>Google Maps App</h1>
<GoogleMap />
</div>
);
}
export default App;
I have error in the console but I don't know if they are connected with this problem.
Here they are:
Warning: Using UNSAFE_componentWillReceiveProps in strict mode is not recommended and may indicate bugs in your code. See https://reactjs.org/link/unsafe-component-lifecycles for details.
Move data fetching code or side effects to componentDidUpdate.
If you're updating state whenever props change, refactor your code to use memoization techniques or move it to static getDerivedStateFromProps. Learn more at: https://reactjs.org/link/derived-state
Please update the following components: Wrapper
Warning: Can't call setState on a component that is not yet mounted. This is a no-op, but it might indicate a bug in your application. Instead, assign to this.state directly or define a state = {}; class property with the desired state in the Wrapper component.
index.js:1 Warning: Using UNSAFE_componentWillReceiveProps in strict mode is not recommended and may indicate bugs in your code. See https://reactjs.org/link/unsafe-component-lifecycles for details.
Move data fetching code or side effects to componentDidUpdate.
If you're updating state whenever props change, refactor your code to use memoization techniques or move it to static getDerivedStateFromProps. Learn more at: https://reactjs.org/link/derived-state
Please update the following components: Wrapper
I saw that other people had this problem also but their solutions didn't help me. Any advice is much appreciated!
You can try to wrap the map container in a div and set it's height and width using css. I think that should work
Just have a small change in div created by the script. It should work
return (
<div id='googleMaps' style="width:200px; height:200px">
<PlacesAutocomplete

How to use "Cloud-based maps styling" in lib "#react-google-maps/api"

I have a React code with . I created in console.cloud "Map styles" and mapId and linked them. Then I added the mapId to the code, but the styles didn't change.
render() {
return (
<LoadScript
mapIds={["xxxxxxxxxxxxx"]}
// id="6e120bcd575d29f7"
googleMapsApiKey="xxxxxxxxxxxxxxxxxxx"
>
<GoogleMap
mapContainerStyle={containerStyle}
center={{
lat: 50.751642333131244,
lng: 25.329876895818945
}}
zoom={17}
>
<Marker
onLoad={this.onLoad}
position={{
lat: 50.7516779698738,
lng: 25.329030658899786
}}
/>
</GoogleMap>
</LoadScript>
)
}
}
To implement Cloud-based maps styling, you need to add the mapId in the Maps Javascript script tag's &map_ids= parameter and the map object mapId parameter. The code you have only adds the mapId in the Maps JavaScript script tag. To add the mapId in your map object parameter, you need to add the mapId option inside your object to implement this styling using the #react-google-maps/api library. See working sample code and code snippet below:
import ReactDOM from "react-dom";
import React from "react";
import {
GoogleMap,
LoadScript
} from "#react-google-maps/api";
const lib = ["places"];
const id = ["6e120bcd575d29f7"]
const key = ""; // PUT GMAP API KEY HERE
const defaultLocation = { lat: 40.756795, lng: -73.954298 };
class Map extends React.Component {
render() {
return (
<div>
<LoadScript googleMapsApiKey={key} libraries={lib} mapIds={id} >
<GoogleMap
center={defaultLocation}
zoom={5}
options={{ mapId: "6e120bcd575d29f7" }}
mapContainerStyle={{ height: "400px", width: "800px" }}
/>
</LoadScript>
</div>
);
}
}
I removed mapId then styles worked.

#react-google-maps Marker LatLng throwing error

I'm using the #react-google-maps/api to build my first react map.. But my latLng literal for position inside the Marker is breaking my code. Is this not the same latLng format that I'm using for center which works fine? How is my Marker latLng wrong? That seems to be the only required attribute in the docs so I'm at a dead end.
import React, { Component } from 'react';
import { GoogleMap, LoadScript, Marker } from '#react-google-maps/api';
import icon1 from '../map/icon1.svg';
import iconDead from '../map/iconDead.svg';
const center = { lat: 51.510228, lng: -0.132992 };
const API = 'xxxx';
const containerStyle = {
width: '100%',
height: '800px'
};
function MyComponent( markers, onToggleOpen ) {
return (
<LoadScript
googleMapsApiKey={API}
>
<GoogleMap
mapContainerStyle={containerStyle}
center={center}
zoom={10}
>
<Marker position={ lat: 51.510228, lng: -0.132992 }></Marker>
<></>
</GoogleMap>
</LoadScript>
)
}
export default React.memo(MyComponent)
The position property is an object. Hand your lat and lng values like this:
<Marker position={{lat: 51.510228, lng: -0.132992}}></Marker>

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.

Resources