1
votes

I have the following code to render multiple markers on a React Google Maps map and the markers do not always render. If I comment out the info for bar 1 and bar 2, save, and uncomment that information the markers will render 80% of the time. If I hard code the current location only, the marker will always render. I have no idea what I’m doing wrong here, most likely an ID-10-T error on my part. Thanks in advance for any help on this matter.

/* global google */

import React from "react"
import { compose, withProps, withStateHandlers } from "recompose"
import {
    withScriptjs,
    withGoogleMap,
    GoogleMap,
    Marker,
    InfoWindow,
} from "react-google-maps"

const MyMapComponent = compose(
    withProps({
        googleMapURL: "https://maps.googleapis.com/maps/api/js?key=[api key goes here]&v=3.exp&libraries=geometry,drawing,places",
        loadingElement: <div style={{ height: `100%` }} />,
        containerElement: <div style={{ height: `600px` }} />,
        mapElement: <div style={{ height: `75vh`, width: '50vw' }} />,
    }),
    withStateHandlers(() => ({
        isOpen: false,
    }), {
            onToggleOpen: ({ isOpen }) => () => ({
                isOpen: !isOpen,
            })
        }),
    withScriptjs,
    withGoogleMap
)((props) =>
    <GoogleMap
        zoom={15}
        center={props.currentLocation}
    >
        {props.markerList.map((marker, index) => {
            return (
                <Marker
                    position={{
                        lat: marker.lat,
                        lng: marker.lng
                    }}
                    onClick={props.onToggleOpen}
                    title={marker.name}
                    key={marker.name}
                >
                    {props.isOpen && <InfoWindow onCloseClick={props.onToggleOpen}>
                        <div>
                            <h3>Info Window</h3>
                            <h4>Testing</h4>
                        </div>
                    </InfoWindow>}
                </Marker>
            )
        })};

    </GoogleMap>
);

const markers = [
    {
        lat: 38.3332416,
        lng: -95.63961839999999,
        name: "bar 1"
    },
    {
        lat: 38.0332416,
        lng: -95.63971639999999,
        name: "bar 2"
    }
];

class MyFancyComponent extends React.PureComponent {
    state = {
        isMarkerShown: false,
    }


    componentWillMount() {
        this.getGeoLocation()
    }

    getGeoLocation = () => {
        if (navigator.geolocation) {
            navigator.geolocation.getCurrentPosition(
                position => {
                    this.setState({
                        currentLatLng: {
                            lat: position.coords.latitude,
                            lng: position.coords.longitude,
                            name: "current location"
                        }
                    })
                    markers.unshift(this.state.currentLatLng);
                }
            )
        } else {
            error => console.log(error)
        }
    }

    render() {
        return (
            <MyMapComponent
                currentLocation={this.state.currentLatLng}
                markerList={markers}
            />
        )
    }
}

export default MyFancyComponent;
1

1 Answers

0
votes

The point is when the position is determined ( callback function of Geolocation.getCurrentPosition() is executed) MyMapComponent component might already get rendered, that's most likely the reason why markers are rendered inconsistently.

To eliminate this behavior the following solution could be considered.

Since MyFancyComponent is already a stateful component i would suggest to introduce markers state and set the initial values like this:

class MyFancyComponent extends React.PureComponent {
  state = {
    isMarkerShown: false,
    markers: markers
  };

  //...
}

Then, once the current location is determined, state could be updated like this:

getGeoLocation = () => {
    if (navigator.geolocation) {
      navigator.geolocation.getCurrentPosition(position => {

        let latLng = {
            lat: position.coords.latitude,
            lng: position.coords.longitude,
            name: "current location"
          };

        this.setState( prevState => ({
          currentLatLng: latLng,
          markers: [latLng,...prevState.markers]
        }));
      });
    } else {
      error => console.log(error);
    }
  };

and finally passed down into MyMapComponent component as props:

<MyMapComponent
        currentLocation={this.state.currentLatLng}
        markerList={this.state.markers}
      />