react-google-maps not showing on screen - google-maps

i have a react app and i am integrating google map using react-google-maps. It fetches data of lat and lng using node server.
Map.js
import { withGoogleMap, GoogleMap, Marker } from "react-google-maps";
import React from 'react';
// Wrap all `react-google-maps` components with `withGoogleMap` HOC
// and name it GettingStartedGoogleMap
export const GettingStartedGoogleMap = withGoogleMap(props => (
<GoogleMap
ref={props.onMapLoad}
defaultZoom={3}
defaultCenter={props.centre[0]}
onClick={props.onMapClick}>
{props.markers.marker.map((marke, index) => (
<Marker
{...marke}
onRightClick={() => props.onMarkerRightClick(index)}
/>
))}
</GoogleMap>
));
export default GettingStartedGoogleMap;
Layout.js
//some imports
const calculate = (x)=>{
var lt=0;
var lg=0;
var count=0;
x.marker.map((k,i)=>(
lt+=k.position.lat,
lg+=k.position.lng,
count++
))
var centre=[{lat:lt/count, lng:lg/count}];
return centre;
};
export const Layout = props => (
//some div and other elements working fine witout map
<div id="map"><GettingStartedGoogleMap
containerElement={
<div style={{ height: `100%` }} />
}
mapElement={
<div style={{ height: `100%` }} />
}
centre={()=>calculate(props.restraun)}
onMapLoad={_.noop}
onMapClick={_.noop}
markers={props.restraun}
onClick={_.noop}
/></div>
//other elements
);
export default Layout;
Maps is not shown in front end. I have included script tag with api key. Tried changing height from % to fixed value. But still doesn't work.
Data is of format
restran:{
marker:[
{position:
{lat:'value',
lng:'value'
}
key:'value'
}]}
data is being shown correctly if printed on console from node
Edit 1: It seems to be error with the component itself as i was able to print some text instead of markers.

Related

React Page Not Outputting Fetch Data

I've recently began studying React and am still trying to get my head around some of it's behaviours.
On the example below I am trying to obtain test data from Github and populate this onto a form. I managed to get promises working and the code is able to retrieve the data. However the data does not populate onto the form and I can't seem to work out where I am going wrong.
I have console logged out 'login' and the data does indeed output the correct data, however the div github-box segment does not seem to get populated with this new information.
I have also tried adding a further .then statement in the promise, in order to send the return ; once the fetch has been completed, but this instead outputs a blank page.
I would be extremely grateful if someone can point me in the right direction.
import logo from './logo.svg';
import React, { useState, useEffect } from 'react';
import { Form, Card, Image, Icon } from 'semantic-ui-react';
import 'semantic-ui-css/semantic.min.css';
import './App.css';
import { GoogleMap, useLoadScript, Marker } from '#react-google-maps/api';
function App() {
const [name, setName] = useState('');
const [followers, setFollowers] = useState('');
const [login, setLogin] = useState('');
useEffect(() => {
fetch('https://api.github.com/users/example')
.then((res) => res.json())
.then((data) => {
console.log(data.login);
setData(data);
});
}, []);
const setData = ({ name, followers }) => {
// setName(name);
setLogin(login);
setFollowers(followers);
};
return <Profile />;
function Profile() {
return (
<div>
<h1>User Profile</h1>
<div className="github-box">
<Card>
<Image
src="https://avatars.githubusercontent.com/u/57936?v=4"
wrapped
ui={false}
/>
<Card.Content>
<Card.Header>Name:{login}</Card.Header>
<Card.Meta>
<span className="date">Joined in 2015</span>
</Card.Meta>
<Card.Description>
Matthew is a musician living in Nashville.
</Card.Description>
</Card.Content>
<Card.Content extra>
<a>
<Icon name="user" />
22 Friends
</a>
</Card.Content>
</Card>
</div>
);
}
}
export default App;

Disable bubbles on embedded google maps

Any idea how to disable these bubbles on my embedded google map?
I'm embedding this into a react/typescript app with react-google-map
Here is my code :
import React, { FC, useState, useEffect } from 'react'
import GoogleMapReact from 'google-map-react'
import Marker from './Marker'
...
export const SimpleMap : FC<any> = ({}) => {
...
return (
<div style={{ height: '80vh', width: '100%', marginTop: '32px' }}>
<GoogleMapReact
bootstrapURLKeys={{ key: 'redacted' }}
defaultCenter={center}
defaultZoom={zoom}
onChildClick={_onChildClick}
//yesIWantToUseGoogleMapApiInternals
onGoogleApiLoaded={({ map, maps }) => apiIsLoaded(map, maps, places)}
>
</GoogleMapReact>
</div>
)
}
Thank you MrUpisdown: Disable bubbles on embedded google maps
The issue was fixed with setting clickableIcons to false
Also see this answer: disable clickable landmark on google map
const apiIsLoaded = (map: any, maps: any, places: any) => {
map.setClickableIcons(false) // Need to call this to disable POIs
...
}
import React, { FC, useState, useEffect } from 'react'
import GoogleMapReact from 'google-map-react'
import Marker from './Marker'
...
export const SimpleMap : FC<any> = ({}) => {
...
return (
<div style={{ height: '80vh', width: '100%', marginTop: '32px' }}>
<GoogleMapReact
bootstrapURLKeys={{ key: 'redacted' }}
defaultCenter={center}
defaultZoom={zoom}
onChildClick={_onChildClick}
yesIWantToUseGoogleMapApiInternals
onGoogleApiLoaded={({ map, maps }) => apiIsLoaded(map, maps, places)}
>
</GoogleMapReact>
</div>
)
}
<GoogleMapReact
bootstrapURLKeys={{
key: ''
}}
defaultCenter={centerPosition}
defaultZoom={14}
onChange={onMapChange}
yesIWantToUseGoogleMapApiInternals
onGoogleApiLoaded={({ map }) => {
mapRef.current = map;
map.setClickableIcons(false)
}}
>

Displaying MapView markers from JSON API

I am using React Native map view (https://github.com/react-native-community/react-native-maps) and have successfully got my map to display with manual markers. However, when I try to display my fetched JSON data markers I get constant syntax errors.
import MapView from 'react-native-maps'
import { Marker } from 'react-native-maps';
constructor(props) {
super(props);
this.state = {
myMarkers: []
};
}
componentDidMount() {
this.getMarkers();
}
getMarkers() {
axios
.get("MYAPISOURCE")
.then(response => {
this.setState({
myMarkers: response.data.responser
});
});
}
render() {
return (
<MapView style={styles.map}
rotateEnabled={false}
initialRegion={{
latitude: 37.78825,
longitude: -122.4324,
latitudeDelta: 0.04,
longitudeDelta: 0.05,
}}
>
{this.state.myMarkers.map((post, index)=> {
<MapView.Marker
key={post.ID}
coordinate={{
latitude:{post.lat},
longitude:{post.lng}}}
/>
})}
</MapView>
);
}
My Map View code which keeps getting syntax error: Unexpected tokens, expected "," in the coordinate function. I have tried so many different options but I cannot get the markers and map to work when I have my marker code.
HOWEVER If I run this code below outside of MapView, it successfully displays my data so my API call and myMarkers state is working and has the proper data:
{this.state.myMarkers.map((post, index)=> {
return (
<View key={index}>
<Text>
{post.lat},
{post.lat}
</Text>
</View>
)
})}
This displays the following:
37.78825, -122.4324
33.78825, -121.4324
31.78825, -124.4324
The data from the service is coming after the rendering(after the components render with empty values) so you need to use promise with state to render it once its ready.
examble:-
constructor(){
super(props);
this.state={dataIsHere:false};
}
dataSource()=>{
axios.<><><>.then((data)=>this.setState({dataIsHere:true}));
}
render(){
return(
...
//It will render markers once the data is ready
{this.state.dataIsHere?
this.state.myMarkers.map((post, index)=> {
<MapView.Marker
key={post.ID}
coordinate={{
latitude:{post.lat},
longitude:{post.lng}}}
/>
}):null}
...
)
}

State element does not appear on react simple map with react-tooltip

The code is working with the property 'name', names appear correctly on the map.
I wanted to enrich the json file with datas coming from my mysql database (like, add the name of countries in french or spanish for example).
I added a state 'countries' which will be initialized with json file converted in object. I fetch data from my sql database and then I set the state 'countries' with data I wanted to add.
Here is the code :
import React, { Component } from "react"
import {
ComposableMap,
ZoomableGroup,
Geographies,
Geography,
} from "react-simple-maps"
import ReactTooltip from "react-tooltip"
import jsonWorldMap from "./maps/world-50m.json"
const wrapperStyles = {
width: "100%",
height: "100%",
backgroundColor: "#0565A1"
}
class WorldMap extends Component {
constructor(){
super()
this.state = {
zoom: 1,
color: "#39464E",
countries: jsonWorldMap
}
}
componentDidMount() {
//get all countries in db
fetch('http://localhost:3001/countries')
.then(res => res.json())
.then(body =>
body.data.forEach(function(elementSql){
jsonWorldMap.objects.units.geometries.forEach(function(elementJson){
if(elementSql.alpha3 == elementJson.id)
{
elementJson.properties.nameFr = elementSql.name_fr;
}
})
})
)
this.setState({ countries: jsonWorldMap }, () => console.log(this.state.countries))
}
render() {
return (
<div style={wrapperStyles}>
<ComposableMap>
<ZoomableGroup center={[0,20]}>
<Geographies geography={this.state.countries}>
{(geographies, projection) => geographies.map((geography, i) => geography.id !== "ATA" && (
<Geography
className="Geography"
key={i}
data-tip={geography.properties.nameFr}
geography={geography}
projection={projection}
/>
))}
</Geographies>
</ZoomableGroup>
</ComposableMap>
<ReactTooltip />
</div>
)
}
}
export default WorldMap
So you can see that I added a component to have a console.log at the end of the component. See what console.log gives :
So you can see that the property 'nameFr' is present in the state object 'countries'. But, If I try to display it as tooltip, it doesn't work. And it works perfectly with property 'name' (in data-tip)
If data-tip={geography.properties.name} works fine but data-tip={geography.properties.nameFr} does not, then it seems that the problem is with state.
See your componentDidMount method. You are updating state with jsonWorldMap at the end of this method.
But as fetch is async , at that moment jsonWorldMap may not be updated yet. So I think you should move that line inside fetch. please see below:
componentDidMount() {
const _this = this; // hold this inside _this
//get all countries in db
fetch('http://localhost:3001/countries')
.then(res => res.json())
.then(body => {
body.data.forEach(function(elementSql){
jsonWorldMap.objects.units.geometries.forEach(function(elementJson){
if(elementSql.alpha3 == elementJson.id)
{
elementJson.properties.nameFr = elementSql.name_fr;
}
})
});
_this.setState({ countries: jsonWorldMap }, () => console.log(this.state.countries)); //making sure setting updated jsonWorldMap to state
}
)
}
hope it helps.
thanks
Wrap Geography with an element that uses data-tip as a props.
<div data-tip={geography.properties.nameFr}>
<Geography ... />
</div>
In order to <Geography data-tip={props.nameFr}/> work, Geography component need to use the data-tip property internaly, something like:
function Geography(props) {
return <h1 data-tip={props['data-tip']}>I'm a map</h1>;
}
To solve your problem you need to attach data-tip property to Geography wrapper, for example:
function Geography(props) {
return <h1>I'm a map</h1>;
}
function ComponentWithTooltip({ props }) {
return (
<div data-tip="nameFr">
<Geography />
</div>
);
}
function App() {
return (
<>
<Geography data-tip="hello-world" /> // Your way, won't work
<ComponentWithTooltip /> // Work
<div data-tip="nameFr2"> // Work
<Geography />
</div>
// Works with div wrapper, without won't work.
{geographies.map((geofraphy, i) => (
<div key={i} data-tip={geofraphy.properties.nameFr}>
<Geography />
</div>
))}
<ReactTooltip />
</>
);
}
Check out the demo with all use cases:

React-google-maps re-rendering issue

I'm having some issues with the react-google-maps npm module.
First render, works like a charm.
When re-rendering the map-component i get the classic google-maps error.
Uncaught TypeError: Cannot read property 'offsetWidth' of null
Uncaught (in promise) TypeError: Cannot read property 'componentWillReceiveProps' of null(…)
Because the map object isn't available when rendering?
My google-maps Map Component
import React, { PropTypes } from 'react'
import { GoogleMap, Marker, GoogleMapLoader } from 'react-google-maps'
export class Map extends React.Component {
static propTypes = {
coordinates: PropTypes.object,
markers: PropTypes.array
};
render () {
return (<section onloadstyle={{height: '300px'}}>
<GoogleMapLoader
containerElement={
<div
{...this.props}
style={{
height: '300px',
width: '100%'
}}
/>
}
googleMapElement={
<GoogleMap
ref={(map) => console.log(map)}
defaultZoom={15}
defaultCenter={this.props.coordinates}>
{this.props.markers.map((marker, index) => {
return (
<Marker key={index} {...marker} />
)
})}
</GoogleMap>
}
/>
</section>)
}
}
export default Map
And i use the component like this:
var coordinates = {lat: this.props.item.delivery_address_lat, lng: this.props.item.delivery_address_lng}
var map = this.props.item.delivery_address_lat !== 0 && this.props.item.delivery_address_lng !== 0 ? (<Row id='map'>
<Map markers={[{position: coordinates}]} coordinates={coordinates} />
</Row>) : ''
Is this because the google-maps-react module isn't unmounting the component properly or is it something i've done?
The following is inside head
<script src="https://maps.googleapis.com/maps/api/js?key=MY-KEY"></script>
EDIT
Tried to solve it a non react-redux way and this is by no means a solution since it produces the error message: Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. Please check the code for the Map component.
But still, the map re-renders correctly. I tried doing this the redux way of calling passed prop functions & state and set the {map: section} in the state, passing it down from the calling view. Didn't solve a thing and resulted in the same error message, even though it was delayed with setTimeout
Im kind of stuck here, don't know how to solve this.
componentDidMount () {
this.setState({map: null})
setTimeout(() => this.setState({
map: <section onloadstyle={{height: '300px'}}>
<GoogleMapLoader
containerElement={
<div
{...this.props}
style={{
height: '300px',
width: '100%'
}}
/>
}
googleMapElement={
<GoogleMap
ref={(map) => console.log(map)}
defaultZoom={15}
defaultCenter={this.props.coordinates}>
{this.props.markers.map((marker, index) => {
return (
<Marker key={index} {...marker} />
)
})}
</GoogleMap>
}
/>
</section>
}), 300)
}
render () {
if (!this.state) {
return <span />
} else {
return this.state.map
}
}
The solution for the second edit was to clear the setTimeout() call in the componentWillUnmount() function.
You always have to clear intervals & timeouts when the component is unmounting.
componentDidMount () {
this.setState({map: null})
this.timeout = setTimeout(() => this.setState({
map: <section onloadstyle={{height: '300px'}}>
<GoogleMapLoader
containerElement={
<div
{...this.props}
style={{
height: '300px',
width: '100%'
}}
/>
}
googleMapElement={
<GoogleMap
ref={(map) => console.log(map)}
defaultZoom={15}
defaultCenter={this.props.coordinates}>
{this.props.markers.map((marker, index) => {
return (
<Marker key={index} {...marker} />
)
})}
</GoogleMap>
}
/>
</section>
}), 300)
}
componentWillUnmount () {
clearTimeout(this.timeout)
}
render () {
if (!this.state) {
return <span />
} else {
return this.state.map
}
}
This solution isn't a good one and isn't in-line with the react-redux workflow. But it works.