React Google Map Marker Not cenetered - reactjs

I am trying to get the map to be centered to the defaultMarker. However, when the map finish loading the view was slightly above the default marker. I have to scroll down to the middle to see the defaultMarker.
Any idea how I can center the view when the map is loaded? I am using React, redux, and react-google-maps.
import React, {Component} from 'react';
import {withGoogleMap, GoogleMap, Marker} from "react-google-maps";
import {connect} from 'react-redux';
class VenuesMap extends Component {
render() {
let markers;
if (this.props.venues !== null) {
markers = this.props.venues.map((venue, i) => {
return (
<Marker
key={i}
position={{ lat: venue.location.lat, lng: venue.location.lng}}
/>
)
})
} else {
markers = <Marker position={{ lat: 40.7589, lng:-73.9851}}/>
}
const MapWithAMarker = withGoogleMap(props =>
<GoogleMap
defaultCenter={{ lat: 40.7589, lng: -73.9851 }}
center={{ lat: 40.7589, lng: -73.9851 }}
zoom={15}
>
{markers}
</GoogleMap>
);
const googleMap = <MapWithAMarker
containerElement={<div style={{
height: `410vh`
}} />}
mapElement={<div style={{ height: `410vh`
}} />}
/>
return (
<div>
{googleMap}
</div>
)
}
}
const stateToProps = (state) => {
return {venues: state.venue.venues}
}
export default connect(stateToProps)(VenuesMap)

maximum window height is 100vh.
just try height: 100vh or less.

Related

Get latitude and longitude on click on Map

I'm doing a little app using React Leaflet, and I want to add a marker on the map every time I click somewhere,
I don't know how to do it, I tried something below but the console log doesn't return something,
function App() {
const [position, setPosition] = useState([48.8534, 2.3488]);
const [markers, setMarkers] = useState([]);
function addMarker(e) {
console.log("e", e);
const newMarker = e;
setMarkers([...markers, newMarker]);
}
return (
<div className="App" style={{ width: "100%", height: "100vh" }}>
<MapContainer
center={position}
zoom={6}
scrollWheelZoom={true}
style={{ width: "100%", height: "100vh" }}
onClick={addMarker}
>
<MyComponent />
<TileLayer url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" />
{markers &&
markers.map((marker, index) => {
<Marker key={`marker-${index}`} position={marker}>
<Popup>
<span>Popup</span>
</Popup>
</Marker>;
})}
</MapContainer>
</div>
);
}
export default App;
react-leaflet just updated to version 3, which no longer support inline events like onClick. You need to use the useMapEvents hook. Example here.
import { MapContainer, useMapEvents } from 'react-leaflet'
function AddMarkerToClick() {
const [markers, setMarkers] = useState([]);
const map = useMapEvents({
click(e) {
const newMarker = e.latlng
setMarkers([...markers, newMarker]);
},
})
return (
<>
{markers.map(marker =>
<Marker position={marker}>
<Popup>Marker is at {marker}</Popup>
</Marker>
)}
</>
)
}
function App() {
return (
<div className="App" style={{ width: "100%", height: "100vh" }}>
<MapContainer {...} > {/* omit onClick */}
<AddMarkerToClick />
</MapContainer>
</div>
);
}
export default App;
I didn't get a chance to test this yet, but this should give you an idea.
import React, { memo, useEffect, useState } from 'react'
import { Map, TileLayer } from 'react-leaflet'
import 'leaflet/dist/leaflet.css'
import Markers from './Markers'
const initialState = ({
lat: '18.4942031',
lng: '-69.8919176',
zoom: '13'
})
export const MapView = memo(({dataMap, searchHistory}) => {
const [ properties, setProperties ] = useState(initialState)
const setPropertiesOnMap = () =>{
setTimeout(function(){
setProperties({
lat: dataMap[0]?.latitude || '18.4942031',
lng: dataMap[0]?.longitude || '-69.8919176',
zoom: '18',
})
},500)
}
useEffect(() =>{
if(dataMap.length === 1){
setPropertiesOnMap()
}else{
setProperties(initialState)
}
//eslint-disable-next-line
},[dataMap])
return (
<Map center={{lat: properties.lat, lng: properties.lng}} zoom={properties.zoom} minZoom={8}>
<TileLayer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
attribution='© OpenStreetMap contributors'
/>
{dataMap[0] && <Markers dataMap={dataMap} searchHistory={searchHistory} />}
</Map>
)
})
I did something similar, I hope it can help you

How do I re-center a GoogleMap React component to a new address using react-google-maps?

I'm rendering a GoogleMap component using the "react-google-maps" library in React. I can set an initial defaultLocation that works fine when the map initially loads. In the documentation it says that the component takes a "center" prop that one can pass a lat and a lng to but I can't get it to re-render/re-center to a new location. It always shows the default location. Any idea what I am doing wrong?
Is there maybe a way how I can use state outside of the addAdressComponent class so I can dynamically set the initial defaultCenter instead of using props in the render section?
import { withGoogleMap, GoogleMap, Marker } from 'react-google-maps';
/*global google*/
const MapWithMarker = withGoogleMap((props) => (
<GoogleMap
defaultZoom={12}
defaultCenter={{ lat: 47.376888, lng: 8.541694 }}
options={{
disableDefaultUI: true,
}}
>
<Marker position={{ lat: 47.376888, lng: 8.541694 }} />
</GoogleMap>
));
class addAddressComponent extends Component {
constructor(props) {
super(props);
this.state = {
lat: 0,
lng: 0,
};
this.onSuggestSelect = this.onSuggestSelect.bind(this);
}
onSuggestSelect(suggest) {
console.log(suggest.location);
this.setState(() => {
return {
lat: 10.0,
lng: 20.022,
};
});
}
render() {
return (
<div className="wrapperClass">
<MapWithMarker
containerElement={<div style={{ height: '244px' }} />}
mapElement={<div style={{ height: '100%' }} />}
className="mapCSS"
center={(this.state.lat, this.state.lng)}
style={{
width: '348px',
height: '250px',
}}
/>
</div>
);
}
}
export default addAddressComponent;
You'll need to pass the center property to your GoogleMap component inside your MapWithMarker component. Also the center argument needs to be an object like this:
{ lat: -34.397, lng: 150.644 }
The following example lets you change the center of the map using the button:
import logo from './logo.svg';
import './App.css';
import { withScriptjs, withGoogleMap, GoogleMap, Marker } from 'react-google-maps';
import {useState} from "react";
const MyMapComponent = withScriptjs(withGoogleMap((props) =>
<GoogleMap
defaultZoom={13}
center={props.center}
defaultCenter={{ lat: -34.397, lng: 150.644 }}
>
{props.isMarkerShown && <Marker position={{ lat: -34.397, lng: 150.644 }} />}
</GoogleMap>
))
function App() {
const [position, setPosition] = useState({ lat: -34.397, lng: 150.644 });
return (
<div className="App">
<button onClick={() => setPosition({lat: 30, lng: 10})}>,
Click me
</button>
<MyMapComponent
isMarkerShown
googleMapURL="https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=geometry,drawing,places"
loadingElement={<div style={{ height: `100%` }} />}
containerElement={<div style={{ height: `100%` }} />}
center={position}
mapElement={<div style={{ height: `1000px`}} />}
/>
</div>
);
}
export default App;

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

Why react-google-maps rendering one Circle component twice?

When I added react-google-maps to project, render worked twice. So I have 2 circles one under another. Also, I display the center coordinates by onDragEnd() method. This event works for only one of this circles.
Any others google maps dosen`t exist on project.
Here is some ways I was trying to fix it:
1) Use only withGoogleMap,
2) Use GoogleMapsWrapper component inside render() method of parent component,
3) Use componentDidMount();
trying everything from satckoverflow :)
and nothing helps.
import React, { Component } from 'react';
import MapForm from './mapForm';
import { GoogleMap, withGoogleMap, withScriptjs, Circle } from 'react-google-maps';
const GoogleMapsWrapper = withScriptjs(withGoogleMap(props => {
const {onMapMounted, ...otherProps} = props;
return <GoogleMap {...otherProps} ref={c => {
onMapMounted && onMapMounted(c)
}}>{props.children}</GoogleMap>
}));
class GoogleMapsContainer extends Component {
state = {
coords: {lat:0, lng: 0}
};
dragCircle = () => {
this.setState({
coords: {
lat: this._circle.getCenter().lat(),
lng: this._circle.getCenter().lng()
}
})
}
render() {
return(
<div style={{display: 'flex',flexDirection: 'row', width: '100%', marginLeft: '37px'}}>
<MapForm
filters={this.props.filters}
coords={this.state.coords}
/>
<GoogleMapsWrapper
googleMapURL={`https://maps.googleapis.com/maps/api/js?key=${KEY}&v=3.exp&libraries=geometry,drawing,places`}
loadingElement={<div style={{height: `100%`}}/>}
containerElement={<div style={{position: 'relative',width: '100%', }} />}
mapElement={<div style={{height: `100%`}}/>}
defaultZoom={13}
defaultCenter={KYIV}
>
<Circle
ref={(circle) => {this._circle = circle}}
defaultCenter = {KYIV}
defaultDraggable={true}
defaultEditable={true}
defaultRadius={2000}
onDragEnd = {this.dragCircle}
options={{
strokeColor: `${colors.vividblue}`,
fillColor: `${colors.vividblue}`,
fillOpacity: 0.1
}}
/>
</GoogleMapsWrapper>
</div>
)
}
}
export default GoogleMapsContainer;
I need only one circle with my methods.mycircles
Ok, the problem was in React StrictMode component in project.

google maps in redux form

i'd like to use google maps for getting lat and long using redux form. I create this:
import React from 'react';
import { compose, withProps, lifecycle } from 'recompose';
import { withScriptjs, withGoogleMap, GoogleMap, Marker } from 'react-google-maps';
const MyMapComponent = compose(
withProps({
googleMapURL:
'https://maps.googleapis.com/maps/api/js?key=AIzaSyCYSleVFeEf3RR8NlBy2_PzHECzPFFdEP0&libraries=geometry,drawing,places',
loadingElement: <div style={{ height: `100%` }} />,
containerElement: <div style={{ height: `400px` }} />,
mapElement: <div style={{ height: `100%` }} />,
}),
lifecycle({
componentWillMount() {
const refs = {};
this.setState({
position: null,
onMarkerMounted: ref => {
refs.marker = ref;
},
onPositionChanged: () => {
const position = refs.marker.getPosition();
console.log(position.toString());
},
});
},
}),
withScriptjs,
withGoogleMap
)(props => (
<GoogleMap defaultZoom={8} defaultCenter={{ lat: -34.397, lng: 150.644 }}>
{props.isMarkerShown && (
<Marker
position={{ lat: -34.397, lng: 150.644 }}
draggable={true}
ref={props.onMarkerMounted}
onPositionChanged={props.onPositionChanged}
/>
)}
</GoogleMap>
));
class MyParentComponentWrapper extends React.PureComponent {
state = {
isMarkerShown: false,
};
render() {
return (
<div>
<MyMapComponent isMarkerShown={true} />
</div>
);
}
}
export default MyParentComponentWrapper;
But it does not return any values and the does not show the lat and long in the field What should i do? it will console.log the lat and long when user drag the marker
If you want MyMapComponent to return the value to MyParentComponentWrapper just pass a callback function as a prop. Just change the parent component to:
<MyMapComponent isMarkerShown={true} onMakerPositionChanged={this.onMakerPositionChanged}/>
and the map component to:
onPositionChanged: () => {
const position = refs.marker.getPosition();
console.log(position.toString());
this.props.onMakerPositionChanged(position);
},
See working example here

Resources