How to re render child component in React hook..useEffect - reactjs

How can i re render this using useeffect geo value getting updated from parent?
import React from 'react'
import { compose } from 'recompose'
import { withGoogleMap, GoogleMap as ReactGoogleMap } from 'react-google-maps'
import Marker from './Marker'
const GoogleMap = compose(withGoogleMap)(({ geo }) => {
console.log(geo)
return (
<ReactGoogleMap
center={{ lat: geo.latitude, lng: geo.longitude }}
options={{
streetViewControl: false,
fullscreenControl: false,
gestureHandling: 'cooperative',
zoom: 18,
}}
>
<Marker loc={geo} />
</ReactGoogleMap>
)
})
export default GoogleMap

Related

Can not read property 'state' of undefined in react nested useState hooks

I am trying to convert this class based to functional component based
here is the actual CLASS BASED CODE
import React, { Component } from 'react';
import L from 'leaflet'
import { Map, TileLayer, Marker, Popup } from 'react-leaflet';
import './App.css';
// Icon properties
var myIcon = L.icon({
iconUrl: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAApCAYAAADAk4LOAAAFgUlEQVR4Aa1XA5BjWRTN2oW17d3YaZtr2962HUzbDNpjszW24mRt28p47v7zq/bXZtrp/lWnXr337j3nPCe85NcypgSFdugCpW5YoDAMRaIMqRi6aKq5E3YqDQO3qAwjVWrD8Ncq/RBpykd8oZUb/kaJutow8r1aP9II0WmLKLIsJyv1w/kqw9Ch2MYdB++12Onxee/QMwvf4/Dk/Lfp/i4nxTXtOoQ4pW5Aj7wpici1A9erdAN2OH64x8OSP9j3Ft3b7aWkTg/Fm91siTra0f9on5sQr9INejH6CUUUpavjFNq1B+Oadhxmnfa8RfEmN8VNAsQhPqF55xHkMzz3jSmChWU6f7/XZKNH+9+hBLOHYozuKQPxyMPUKkrX/K0uWnfFaJGS1QPRtZsOPtr3NsW0uyh6NNCOkU3Yz+bXbT3I8G3xE5EXLXtCXbbqwCO9zPQYPRTZ5vIDXD7U+w7rFDEoUUf7ibHIR4y6bLVPXrz8JVZEql13trxwue/uDivd3fkWRbS6/IA2bID4uk0UpF1N8qLlbBlXs4Ee7HLTfV1j54APvODnSfOWBqtKVvjgLKzF5YdEk5ewRkGlK0i33Eofffc7HT56jD7/6U+qH3Cx7SBLNntH5YIPvODnyfIXZYRVDPqgHtLs5ABHD3YzLuespb7t79FY34DjMwrVrcTuwlT55YMPvOBnRrJ4VXTdNnYug5ucHLBjEpt30701A3Ts+HEa73u6dT3FNWwflY86eMHPk+Yu+i6pzUpRrW7SNDg5JHR4KapmM5Wv2E8Tfcb1HoqqHMHU+uWDD7zg54mz5/2BSnizi9T1Dg4QQXLToGNCkb6tb1NU+QAlGr1++eADrzhn/u8Q2YZhQVlZ5+CAOtqfbhmaUCS1ezNFVm2imDbPmPng5wmz+gwh+oHDce0eUtQ6OGDIyR0uUhUsoO3vfDmmgOezH0mZN59x7MBi++WDL1g/eEiU3avlidO671bkLfwbw5XV2P8Pzo0ydy4t2/0eu33xYSOMOD8hTf4CrBtGMSoXfPLchX+J0ruSePw3LZeK0juPJbYzrhkH0io7B3k164hiGvawhOKMLkrQLyVpZg8rHFW7E2uHOL888IBPlNZ1FPzstSJM694fWr6RwpvcJK60+0HCILTBzZLFNdtAzJaohze60T8qBzyh5ZuOg5e7uwQppofEmf2++DYvmySqGBuKaicF1blQjhuHdvCIMvp8whTTfZzI7RldpwtSzL+F1+wkdZ2TBOW2gIF88PBTzD/gpeREAMEbxnJcaJHNHrpzji0gQCS6hdkEeYt9DF/2qPcEC8RM28Hwmr3sdNyht00byAut2k3gufWNtgtOEOFGUwcXWNDbdNbpgBGxEvKkOQsxivJx33iow0Vw5S6SVTrpVq11ysA2Rp7gTfPfktc6zhtXBBC+adRLshf6sG2RfHPZ5EAc4sVZ83yCN00Fk/4kggu40ZTvIEm5g24qtU4KjBrx/BTTH8ifVASAG7gKrnWxJDcU7x8X6Ecczhm3o6YicvsLXWfh3Ch1W0k8x0nXF+0fFxgt4phz8QvypiwCCFKMqXCnqXExjq10beH+UUA7+nG6mdG/Pu0f3LgFcGrl2s0kNNjpmoJ9o4B29CMO8dMT4Q5ox8uitF6fqsrJOr8qnwNbRzv6hSnG5wP+64C7h9lp30hKNtKdWjtdkbuPA19nJ7Tz3zR/ibgARbhb4AlhavcBebmTHcFl2fvYEnW0ox9xMxKBS8btJ+KiEbq9zA4RthQXDhPa0T9TEe69gWupwc6uBUphquXgf+/FrIjweHQS4/pduMe5ERUMHUd9xv8ZR98CxkS4F2n3EUrUZ10EYNw7BWm9x1GiPssi3GgiGRDKWRYZfXlON+dfNbM+GgIwYdwAAAAASUVORK5CYII',
iconSize: [25, 41],
iconAnchor: [22, 94],
popupAnchor: [-10, -90],
});
export default class Fullmap extends Component {
state = {
location: {
lat: 51.097,
lng: -1.505
},
haveUsersLocation: false,
zoom: 2
}
componentDidMount(){
// Get GeoLocation for setting marker from browser on page load
navigator.geolocation.getCurrentPosition((position) =>{
this.setState({
location:{
lat: position.coords.latitude,
lng: position.coords.longitude
},
haveUsersLocation: true,
zoom: 13
});
}, ()=>{
// If denied location via browser, get via IP
fetch('https://ipapi.co/json')
.then(res => res.json())
.then(location =>{
this.setState({
location:{
lat: location.latitude,
lng: location.longitude
},
haveUsersLocation: true,
zoom: 13
});
})
});
}
render(){
const position = [this.state.location.lat, this.state.location.lng];
return (
<div className="App">
<Map className="Map" center={position} zoom={this.state.zoom}>
<TileLayer
attribution='&copy OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
{this.state.haveUsersLocation ?
<Marker
icon={myIcon}
position={position}>
<Popup>
A pretty CSS3 popup. <br /> Easily customizable.
</Popup>
</Marker> : ''
}
</Map>
</div>
);
}
}
This is working fine with no error whereas now when i converted it to below functional based code
import React, { useState, useEffect } from 'react';
import L from 'leaflet'
import { Map, TileLayer, Marker, Popup } from 'react-leaflet';
import './App.css';
// Icon properties
var myIcon = L.icon({
iconUrl: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAApCAYAAADAk4LOAAAFgUlEQVR4Aa1XA5BjWRTN2oW17d3YaZtr2962HUzbDNpjszW24mRt28p47v7zq/bXZtrp/lWnXr337j3nPCe85NcypgSFdugCpW5YoDAMRaIMqRi6aKq5E3YqDQO3qAwjVWrD8Ncq/RBpykd8oZUb/kaJutow8r1aP9II0WmLKLIsJyv1w/kqw9Ch2MYdB++12Onxee/QMwvf4/Dk/Lfp/i4nxTXtOoQ4pW5Aj7wpici1A9erdAN2OH64x8OSP9j3Ft3b7aWkTg/Fm91siTra0f9on5sQr9INejH6CUUUpavjFNq1B+Oadhxmnfa8RfEmN8VNAsQhPqF55xHkMzz3jSmChWU6f7/XZKNH+9+hBLOHYozuKQPxyMPUKkrX/K0uWnfFaJGS1QPRtZsOPtr3NsW0uyh6NNCOkU3Yz+bXbT3I8G3xE5EXLXtCXbbqwCO9zPQYPRTZ5vIDXD7U+w7rFDEoUUf7ibHIR4y6bLVPXrz8JVZEql13trxwue/uDivd3fkWRbS6/IA2bID4uk0UpF1N8qLlbBlXs4Ee7HLTfV1j54APvODnSfOWBqtKVvjgLKzF5YdEk5ewRkGlK0i33Eofffc7HT56jD7/6U+qH3Cx7SBLNntH5YIPvODnyfIXZYRVDPqgHtLs5ABHD3YzLuespb7t79FY34DjMwrVrcTuwlT55YMPvOBnRrJ4VXTdNnYug5ucHLBjEpt30701A3Ts+HEa73u6dT3FNWwflY86eMHPk+Yu+i6pzUpRrW7SNDg5JHR4KapmM5Wv2E8Tfcb1HoqqHMHU+uWDD7zg54mz5/2BSnizi9T1Dg4QQXLToGNCkb6tb1NU+QAlGr1++eADrzhn/u8Q2YZhQVlZ5+CAOtqfbhmaUCS1ezNFVm2imDbPmPng5wmz+gwh+oHDce0eUtQ6OGDIyR0uUhUsoO3vfDmmgOezH0mZN59x7MBi++WDL1g/eEiU3avlidO671bkLfwbw5XV2P8Pzo0ydy4t2/0eu33xYSOMOD8hTf4CrBtGMSoXfPLchX+J0ruSePw3LZeK0juPJbYzrhkH0io7B3k164hiGvawhOKMLkrQLyVpZg8rHFW7E2uHOL888IBPlNZ1FPzstSJM694fWr6RwpvcJK60+0HCILTBzZLFNdtAzJaohze60T8qBzyh5ZuOg5e7uwQppofEmf2++DYvmySqGBuKaicF1blQjhuHdvCIMvp8whTTfZzI7RldpwtSzL+F1+wkdZ2TBOW2gIF88PBTzD/gpeREAMEbxnJcaJHNHrpzji0gQCS6hdkEeYt9DF/2qPcEC8RM28Hwmr3sdNyht00byAut2k3gufWNtgtOEOFGUwcXWNDbdNbpgBGxEvKkOQsxivJx33iow0Vw5S6SVTrpVq11ysA2Rp7gTfPfktc6zhtXBBC+adRLshf6sG2RfHPZ5EAc4sVZ83yCN00Fk/4kggu40ZTvIEm5g24qtU4KjBrx/BTTH8ifVASAG7gKrnWxJDcU7x8X6Ecczhm3o6YicvsLXWfh3Ch1W0k8x0nXF+0fFxgt4phz8QvypiwCCFKMqXCnqXExjq10beH+UUA7+nG6mdG/Pu0f3LgFcGrl2s0kNNjpmoJ9o4B29CMO8dMT4Q5ox8uitF6fqsrJOr8qnwNbRzv6hSnG5wP+64C7h9lp30hKNtKdWjtdkbuPA19nJ7Tz3zR/ibgARbhb4AlhavcBebmTHcFl2fvYEnW0ox9xMxKBS8btJ+KiEbq9zA4RthQXDhPa0T9TEe69gWupwc6uBUphquXgf+/FrIjweHQS4/pduMe5ERUMHUd9xv8ZR98CxkS4F2n3EUrUZ10EYNw7BWm9x1GiPssi3GgiGRDKWRYZfXlON+dfNbM+GgIwYdwAAAAASUVORK5CYII',
iconSize: [25, 41],
iconAnchor: [22, 94],
popupAnchor: [-10, -90],
});
export default function MyMap() {
const [location, setLocation] = useState({
lat: false,
lng: null,
zoom: 2,
usersLocation: false
});
useEffect(() => {
// Get GeoLocation for setting marker from browser on page load
navigator.geolocation.getCurrentPosition((position) =>{
setLocation([...location,{
lat: position.coords.latitude,
lng: position.coords.longitude,
haveUsersLocation: true,
zoom: 13
}]);
}, ()=>{
// If denied location via browser, get via IP
fetch('https://ipapi.co/json')
.then(res => res.json())
.then(location =>{
setLocation([...location,{
lat: location.coords.latitude,
lng: location.coords.longitude,
haveUsersLocation: true,
zoom: 13
}]);
})
});
});
const position = [location.lat, location.lng];
return (
<div className="App">
<Map className="Map" center={position} zoom={location.zoom}>
<TileLayer
attribution='&copy OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
{this.state.haveUsersLocation ?
<Marker
icon={myIcon}
position={position}>
<Popup>
A pretty CSS3 popup. <br /> Easily customizable.
</Popup>
</Marker> : ''
}
</Map>
</div>
);
}
it is giving me error as TypeError: Cannot read property 'state' of undefined on Line No. 54
I would really appreciate if you could help me point out my error and also explain a bit as I'm pretty new to react.
A functional component doesn't have a this to access the state. You can just reference the state variables directly, in your case location
To expand:
in a class component this refers to the class instance, where the state is stored. In a functional component you gain access to the state via the state variable returned from the useState hook
Only class components have access to this. if you would like to get the current state of haveUsersLocation just simply use location.haveUsersLocation
instead of
{this.state.haveUsersLocation ?
<Marker
...
}
use
{location.haveUsersLocation ?
<Marker
...
}
you have used useState const [location, setLocation] = useState so you can get updated state directly from location variable.

How to disable street view with react-google-maps?

I'm using the react-google-maps package to render a Google Map in my react application. I would like to disable street view.
From the documentation, I see there are props for:
defaultStreetView
streetView
I have tried using both with false - but neither works. Does anyone know how to disable street view functionality via this package?
Code snippet here:
import React, { Component } from 'react';
import { withScriptjs, withGoogleMap, GoogleMap, Marker } from "react-google-maps";
import PropTypes from 'prop-types';
const Map = withScriptjs(withGoogleMap((props) => {
return(
<GoogleMap
defaultZoom={17}
defaultCenter={{ lat: props.lat, lng: props.lng }}
// defaultStreetView={false}
// streetView={false}
>
{props.isMarkerShown && <Marker position={{ lat: props.lat, lng: props.lng }} />}
</GoogleMap>
)
}))
Map.propTypes = {
lat: PropTypes.number.isRequired,
lng: PropTypes.number.isRequired,
isMarkerShown: PropTypes.bool.isRequired
}
export default Map;
It seems the props defaultStreetView and streetView were actually not relevant in this case.
The way to implement this is to pass { streetViewControl: false } to the options prop.
Correct code:
import React, { Component } from 'react';
import { withScriptjs, withGoogleMap, GoogleMap, Marker } from "react-google-maps";
import PropTypes from 'prop-types';
const Map = withScriptjs(withGoogleMap((props) => {
return(
<GoogleMap
defaultZoom={17}
defaultCenter={{ lat: props.lat, lng: props.lng }}
options={{streetViewControl: false}}
>
{props.isMarkerShown && <Marker position={{ lat: props.lat, lng: props.lng }} />}
</GoogleMap>
)
}))
Map.propTypes = {
lat: PropTypes.number.isRequired,
lng: PropTypes.number.isRequired,
isMarkerShown: PropTypes.bool.isRequired
}
export default Map;

how to display google map marker in google-map-react

hi all im trying to make google maps in react take lat and long from different component and display marker based on that. However the marker is not showing up when i put lat and long values. this.state.lat and long is definetly correct because my map does update but marker is nowhere to be found. Any help is greatly appreciated!
map.js
import React, { Component } from 'react';
import GoogleMapReact from 'google-map-react';
import marker from './marker.png';
import { geolocated } from 'react-geolocated';
const AnyReactComponent = ({ text }) => (
<div>
<img src={marker} style={{ height: '50px', width: '50px' }} />
</div>
);
export default class Map extends Component {
static defaultProps = {
zoom: 11,
};
Componentwillmount() {
console.log(this.props.center.latitude);
}
render() {
return (
<div className="google-map" style={{ width: '100%', height: '2000px', backgroundColor: 'red' }}>
<GoogleMapReact
options={{
styles:ExampleMapStyles
}}
center={this.props.center} defaultZoom={this.props.zoom}>
<AnyReactComponent
lat={this.props.center.latitude}
lng={this.props.center.longitude}
text={'Kreyser Avrora'}
/>
</GoogleMapReact>
</div>
);
}
}
home.js
import React, { Component } from 'react';
import axios from 'axios';
import './App.css';
import PlacesAutocomplete from 'react-places-autocomplete';
import { geocodeByAddress, geocodeByPlaceId, getLatLng } from 'react-places-autocomplete';
import UserForm from './UserForm.js';
import { classnames } from './helpers';
import marker from './marker.png';
import Nav from './nav';
import Food from './food';
import Tool from './tools';
import Health from './health';
import MapContainer from './Map';
import Map from './Map';
import { BrowserRouter as Router, Route, Link } from 'react-router-dom';
class Home extends Component {
constructor() {
super();
this.state = {
zoom: 13,
maptype: 'roadmap',
place_formatted: '',
place_id: '',
place_location: '',
address: '',
value:'',
latitude: 37.774929,
longitude: -122.419416,
marker: [],
place: [],
isLoaded2: false,
places2: [],
isLoaded: false,
isLoaded3: false,
};
}
render() {
return (
<div id="h">
<Map center={{ lat: this.state.latitude, lng: this.state.longitude }} />
<div />
);
}
}
export default Home;
You try to get the following attributes of the props object:
<AnyReactComponent
lat={this.props.center.latitude}
lng={this.props.center.longitude}
text={'Kreyser Avrora'}
/>
But the object you hand in the props has the attributes lat and lng:
center={{ lat: this.state.latitude, lng: this.state.longitude }}
Changing your AnyReactComponent to use this.props.center.lat and .lng should make it work.

Update Google Map based on Geolocation with React

I'm trying to show Google Map with centering the map based on latitude and longitude which are returned by Geolocation. However, the map shows as the default value and not get rendered by Geolocation values. I set latitude and longitude in component state and trying to re-render the component after the state is updated. But it does not work. Below is my code.
MapView.js
import React, { Component } from 'react'
import { withScriptjs, withGoogleMap, GoogleMap, Marker } from 'react-google-maps'
import MapComponent from './MapComponent'
class MapView extends Component {
constructor(props){
super(props)
this.state = {
currentLatLng: {
lat: 0,
lng: 0
},
isMarkerShown: false
}
}
componentWillUpdate(){
this.getGeoLocation()
}
componentDidMount() {
this.delayedShowMarker()
}
delayedShowMarker = () => {
setTimeout(() => {
this.getGeoLocation()
this.setState({ isMarkerShown: true })
}, 5000)
}
handleMarkerClick = () => {
this.setState({ isMarkerShown: false })
this.delayedShowMarker()
}
getGeoLocation = () => {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
position => {
this.setState({
lat: position.coords.latitude,
lng: position.coords.longitude
})
}
)
} else {
error => console.log(error)
}
}
render() {
return (
<MapComponent
isMarkerShown={this.state.isMarkerShown}
onMarkerClick={this.handleMarkerClick}
currentLocation={this.state.currentLatLng}
/>
)
}
}
export default MapView;
MapComponent.js
import React, { Component } from 'react'
import { compose, withProps } from 'recompose'
import { withScriptjs, withGoogleMap, GoogleMap, Marker } from 'react-google-maps'
const MapComponent = compose(
withProps({
googleMapURL: "https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=geometry,drawing,places",
loadingElement: <div style={{ height: `100%` }} />,
containerElement: <div style={{ height: `400px` }} />,
mapElement: <div style={{ height: `100%` }} />,
}),
withScriptjs,
withGoogleMap
)((props) =>
<GoogleMap
defaultZoom={8}
defaultCenter={{ lat: props.currentLocation.lat, lng: props.currentLocation.lng }}
>
{props.isMarkerShown && <Marker position={{ lat: props.currentLocation.lat, lng: props.currentLocation.lng }} onClick={props.onMarkerClick} />}
</GoogleMap>
)
export default MapComponent
In fact map is not centered since currentLatLng is not getting updated, you might want something like this:
getGeoLocation = () => {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
position => {
console.log(position.coords);
this.setState(prevState => ({
currentLatLng: {
...prevState.currentLatLng,
lat: position.coords.latitude,
lng: position.coords.longitude
}
}))
}
)
} else {
error => console.log(error)
}
}
instead of original getGeoLocation function
According to w3.org, the current location can be obtained with:
function showMap(position) {
// Show a map centered at (position.coords.latitude, position.coords.longitude).
console.log(position.coords.latitude);
console.log(position.coords.longitude);
}
// One-shot position request.
navigator.geolocation.getCurrentPosition(showMap);
This links Geolocation API:
Geolocation API w3.org
This worked for me, location high accuracy.

Google map coordinates in react

I'm trying to get the current position on google map. The code is working fine when I get the coordinates, but these coordinates I want to get and google map toom because right now, coordinates are static for google map.
import React, { Component } from 'react';
import GoogleMapReact from 'google-map-react';
import { withGoogleMap, GoogleMap, Marker } from "google-map-react"
import { InfoWindow } from 'google-map-react';
import Geolocation from 'react-geolocation'
const AnyReactComponent = ({ text }) => <div>{ text }</div>;
export default class Map extends Component {
static defaultProps = {
center: { lat: 40.7446790, lng: -73.9485420 },
zoom: 11
}
render() {
return (
<Geolocation
render={({
fetchingPosition,
position: { coords: { latitude, longitude } = {} } = {},
error,
getCurrentPosition
}) =>
<div>
<button onClick={getCurrentPosition}>Get Position</button>
{error &&
<div>
{error.message}
</div>}
<pre>
latitude: {latitude}
longitude: {longitude}
</pre>
<div className='google-map' style={{ height: '80vh', width: '100%' }}>
<GoogleMapReact
defaultCenter={ this.props.center }
defaultZoom={ this.props.zoom }>
<AnyReactComponent
lat={ latitude }
lng={ longitude }
text={ 'Wheres Waldo?' }
/>
</GoogleMapReact>
</div>
</div>}
/>
)
}
}
With Geolocation I get very well coordinates, but these coordinates want to set in:
static defaultProps = {
center: { lat: 40.7446790, lng: -73.9485420 },
zoom: 11
}
You must define a state for your <Map> component, which will store your current coordinates.
Then, you should pass the state to your GoogleMapReact component.
In order to set the state with the coordinates found by the Geolocation services, you can use onSuccess callback (https://www.npmjs.com/package/react-geolocation#onsuccess-function):
<Geolocation
onSuccess={this.geoSuccess}
...
/>
The geoSuccess function is:
geoSuccess = position => {
let coords = {
lat: position.coords.latitude,
lng: position.coords.longitude
}
this.setState({
center: coords
})
};
Demo here:
https://43qv620770.codesandbox.io/
The full code can be found here (the file Map.js):
https://codesandbox.io/s/43qv620770

Resources