Access variable outside render - reactjs

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.

Related

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

react-google-maps: multiple info windows opening up

This is probably going to be a stupidly simple react question but please bear with me.
I am trying to run a react-google-maps with multiple markers with info windows. Here is the code:
const MapWithADirectionsRenderer = compose(
withProps({
googleMapURL: "https://maps.googleapis.com/maps/api/js?key=AIzaSyDf-yIqxErTkbWzKhLox7nAANnrfDIY190&libraries=geometry,drawing,places",
loadingElement: <div style={{ height: `100%` }} />,
containerElement: <div style={{ height: `800px` }} />,
mapElement: <div style={{ height: `100%` }} />,
}),
withStateHandlers(() => ({
isOpen: false,
}), {
onToggleOpen: ({ isOpen }) => () => ({
isOpen: !isOpen,
})
}),
withScriptjs,
withGoogleMap,
})
)(props =>
<GoogleMap
defaultZoom={13}
defaultCenter={new google.maps.LatLng(42.357064, -71.062577)}
>
<Marker
position={{ lat: 42.3381437, lng: -71.0475773 }}
onClick={props.onToggleOpen}
>
{props.isOpen && <InfoWindow onCloseClick={props.onToggleOpen}>
<h3>South Boston</h3>
</InfoWindow>}
</Marker>
<Marker
position={{ lat: 42.3875968, lng: -71.0994968 }}
onClick={props.onToggleOpen}
>
{props.isOpen && <InfoWindow onCloseClick={props.onToggleOpen}>
<h3>Somervil</h3>
</InfoWindow>}
</Marker>
{props.directions && <DirectionsRenderer directions={props.directions} />}
</GoogleMap>
);
When I click one of the markers, the info windows for all the markers toggle open. How do I just toggle open the info window of the marker I click?
I would suggest to introduce a component:
class MarkerWithInfoWindow extends React.Component {
constructor() {
super();
this.state = {
isOpen: false
}
this.onToggleOpen = this.onToggleOpen.bind(this);
}
onToggleOpen() {
this.setState({
isOpen: !this.state.isOpen
});
}
render() {
return (<Marker
position={this.props.position}
onClick={this.onToggleOpen}>
{this.state.isOpen && <InfoWindow onCloseClick={this.onToggleOpen}>
<h3>{this.props.content}</h3>
</InfoWindow>}
</Marker>)
}
}
to control info window per marker via MarkerWithInfoWindow state:
<GoogleMap
defaultZoom={13}
defaultCenter={new google.maps.LatLng(42.357064, -71.062577)}>
<MarkerWithInfoWindow position={{ lat: 42.3381437, lng: -71.0475773 }} content="South Boston" />
<MarkerWithInfoWindow position={{ lat: 42.3875968, lng: -71.0994968 }} content="Somervil" />
</GoogleMap>
Demo

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)

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

react-google-maps : Can't get bounds

I have the following react component that loads a GoogleMap from 'react-google-maps' library. I'm following the documentation examples but I get undefined from getBounds() function. I think it is due to trying to get the bounds before map is fully loaded but can't find a solution.
#inject("map") #observer
export default class Map extends Component {
constructor(props) {
super(props);
}
render() {
const mapStore = this.props.map
const GettingStartedGoogleMap = withGoogleMap(props => (
<GoogleMap
ref={props.onMapLoad}
style={{
height: 100,
width: 100,
}}
defaultOptions={{ styles: this.mapStyles }}
defaultZoom={mapStore.zoom}
defaultCenter={{ lat: mapStore.center.lat, lng: mapStore.center.lng }}>
{
mapStore.markers.map(({ lat, lng }) => {
return <Marker
position={{ lat, lng }}
icon={{
url: require('../../images/marker.png')
}}
/>
})
}
</GoogleMap>
))
return (
<GettingStartedGoogleMap
style={{
height: 100,
width: 100,
}}
onMapLoad={(googleMap) => {
console.log(googleMap.getBounds())
}}
containerElement={
<div style={{ height: 'calc(100vh - 70px)' }
} />
}
mapElement={
<div style={{ height: 'calc(100vh - 70px)' }} />
} />
)
}
}
Thanks in advance
you can use 'onIdle' to make sure map is fully ready
<GoogleMap
ref={props.onMapLoad}
...
onIdle={props.onMapIdle}
>
...
</GoogleMap>
and
<GettingStartedGoogleMap
onMapIdle={ ()=> { console.log('map is ready') } }
...
/>

Resources