Skip to content
Advertisement

google-maps-react – Specific Pins not Showing up until Click

SparkNotes:

I’m pulling in a crime API to see hotspots. Certain crimes will not be logged with a lat/long, therefore, are not shown up in standard (free) crime apps.

  • Lat/Long pins I’ve overridden to a new lat/long don’t show up on first load/or at all. (google-maps-react) (Confirmed lat/long is valid per crimes in near areas.)
  • Normal pins that had an existing lat/long show up fine/show up as soon as it loads. (Even though it’s all the same array of data.)
  • I loop through the blank lat/long and replace the lat/long with a rough lat/long of the area just so it shows up. In my console log I can confirm that I’ve overriden the blank lat/long.
  • I want these records to understand the neighborhoods/potentially avoid moving into a hotspot of specific crimes.

API Normal:
https://data.seattle.gov/resource/tazs-3rd5.json?$limit=20000&$offset=20000&$order=offense_id

Specific Items: https://data.seattle.gov/resource/tazs-3rd5.json?$where=report_number%20in(%272020-022388%27,%272020-044620%27,%272020-043813%27,%272020-029645%27,%272020-901621%27)

Full Use Case (Which doesn’t work for at all pins): https://data.seattle.gov/resource/tazs-3rd5.json?crime_against_category=PERSON&mcpp=MAGNOLIA&offense_parent_group=SEX%20OFFENSES

Request for help: Can someone please help on how to get these overridden pins to show up consistently?

Things I’ve Tried: Force update/having multiple refreshes etc/decreasing async time. Those work for when I put in specific crime report number, but if I search for kidnapping/peeping tom, they will not pull with the rest of the person crimes.

I can confirm that if I just load every crime in that API, the map logs all of them (except the ones I need), It’s like a pin per foot of street, but the pins in the categories I need don’t show up. (So I don’t believe it’s a volume issue.)

Code for API Data:

const endpoint = 'https://data.seattle.gov/resource/tazs-3rd5.json?$where=report_number%20in(%272020-022388%27,%272020-044620%27)'
const originalplaces = [];
const places = []
fetch(endpoint)
.then(blob => blob.json())
.then(data => originalplaces.push(...data));



async function returnTrue() {


  // create a new promise inside of the async function
  let promise = new Promise((resolve, reject) => {

    setTimeout(() => resolve(true), 1000) // resolve
  });


  // wait for the promise to resolve
  let result = await promise;
  // originalplaces.mcpp === 'MAGNOLIA' && originalplaces.longitude == '0E-9'   && originalplaces.longitude.replace("0E-9", "-122.385973723")
  // originalplaces.forEach(function(mcpp, i) { if (mcpp == 'MAGNOLIA') originalplaces[i] = '47.649387230'; });
  originalplaces.map(object => {

    if (object.mcpp === 'MAGNOLIA' && object.longitude === '0E-9' && object.latitude === '0E-9')

     {  object.longitude = "-122.391970804"
     object.latitude = "47.63103937"
    }


  })
  places.push(...originalplaces)


  console.log(places)


  // console log the result (true)
  console.log(result);
}

// call the function
returnTrue();

export default originalplaces;

Code for Map

import React, { Component } from "react";
import { Map, InfoWindow, Marker, GoogleApiWrapper } from "google-maps-react";

import places from './crimedata.js'

class MapView extends Component {
  constructor(props) {
    super(props)
    this.state = {
      showingInfoWindow: false,
      activeMarker: {},
      selectedPlace: {},

    };
    this.handleMarkerClick = this.handleMarkerClick.bind(this);
    this.handleClose = this.handleClose.bind(this);
  }



  handleMarkerClick = (props, marker, e) => {
    this.setState({
      selectedPlace: places[props.placeIndex],
      activeMarker: marker,
      showingInfoWindow: true,

    });
  };

  handleClose = () => {
    if (this.state.showingInfoWindow) {
      this.setState({
        showingInfoWindow: false,
        activeMarker: null
      });
    }
  };

  render() {

    return (
      <Map
        google={this.props.google}
        className={"map"}
        initialCenter={{ lat: 47.6205, lng: -122.3493}}
        style={{ height: '100vh', width: '100%' }}
      >

        {places.map((place, i) => {
          return (



            <Marker
              key={i}
              onClick={this.handleMarkerClick}
              position={{
                lat: parseFloat(place.latitude),
                lng: parseFloat(place.longitude)

              }}

              icon={{

                url: place.offense_parent_group === "ASSAULT OFFENSES" ? "/googlemarkersyellow.svg"
                : place.offense_parent_group === "BURGLARY/BREAKING&ENTERING" ?"/googlemarkersdarkorange.svg"
                : place.offense_parent_group === "TRESPASS OF REAL PROPERTY" ?"/googlemarkersorange.svg"
                : place.offense_parent_group === "STOLEN PROPERTY OFFENSES" ?"/googlemarkersgreen.svg"
                : place.offense_parent_group === "SEX OFFENSES" ?"/googlemarkersblack.svg"
                : place.offense_parent_group === "DESTRUCTION/DAMAGE/VANDALISM OF PROPERTY" ?"/googlemarkersdarkgreen.svg"
                : place.offense_parent_group === "DRUG/NARCOTIC OFFENSES" ?"/googlemarkersdarkgray.svg"
                : place.offense_parent_group === "ROBBERY" ?"/googlemarkersdarkpurple.svg"
                : place.offense_parent_group === "MOTOR VEHICLE THEFT " ?"/googlemarkerspink.svg"
                : place.offense_parent_group === "HOMICIDE OFFENSES" ?"/googlemarkersteal.svg"
                : place.offense_parent_group === "ARSON" ?"/googlemarkerslightblue.svg"
                : place.offense_parent_group === "HUMAN TRAFFICKING" ?"/googlemarkersteal.svg"
                : place.offense_parent_group === "PROSTITUTION OFFENSES" ?"/googlemarkerstan.svg"

                : `/googlemarkerdefault.svg`,
                scaledSize: new window.google.maps.Size(50, 50)
              }}
              placeIndex={i}
              name={place.offense}
            />

          );
        })}

        <InfoWindow
          marker={this.state.activeMarker}
          visible={this.state.showingInfoWindow}
          onClose={this.handleClose}

        >
          <div> <h6>{this.state.selectedPlace.offense}</h6>
         <p> {'Crime: ' + this.state.selectedPlace.offense_parent_group}</p>
         <p> {'City: ' + this.state.selectedPlace.mcpp}</p>
         <p> {'Report Date: ' +this.state.selectedPlace.report_datetime}</p>
         <p> {'Report Number: ' + this.state.selectedPlace.report_number}</p>



          </div>
        </InfoWindow>
      </Map>
    );
  }
}

export default GoogleApiWrapper({
  apiKey: process.env.REACT_APP_GOOGLEMAPS
})(MapView);


Screenshots:

Prior to Clicking

AfterClicking

Last Notes: I have overrides for all the cities, which is why you see 4 pins, in my screenshot, but code only has override for one city, if I include all, it’s really long.

Advertisement

Answer

It seems that there’s a timing issue when importing your places data from crimedata.js in the first load of the code. I can see that the places value is empty [] in the initial run then the loading of your places in your crimedata.js will follow after some time. You can see this in the console log in my working code.

To handle this, I used state variables to hold the value of the updatedPlaces data then in componentDidMount function, I used setTimeOut and set value of updatedPlaces state variable from the imported places data that is now available.

I then used this state variable as a condition for the markers to load.

Here’s the code snippet:

import React, { Component } from "react";
import { Map, InfoWindow, Marker, GoogleApiWrapper } from "google-maps-react";

import places from "./crimedata.js";
console.log("upon importing crimedata.js");
console.log(places);
class MapView extends Component {
  constructor(props) {
    super(props);
    this.state = {
      updatedPlaces: null,
      showingInfoWindow: false,
      activeMarker: {},
      selectedPlace: {}
    };
    this.handleMarkerClick = this.handleMarkerClick.bind(this);
    this.handleClose = this.handleClose.bind(this);
  }

  componentDidMount() {
    //console.log(places);

    setTimeout(() => {
      this.setState({
        updatedPlaces: places
      });
      console.log("timeOut in componentDidMount");
      console.log(this.state.updatedPlaces);
    }, 1000);
  }

  handleMarkerClick = (props, marker, e) => {
    this.setState({
      selectedPlace: places[props.placeIndex],
      activeMarker: marker,
      showingInfoWindow: true
    });
  };

  handleClose = () => {
    if (this.state.showingInfoWindow) {
      this.setState({
        showingInfoWindow: false,
        activeMarker: null
      });
    }
  };

  render() {
    return (
      <Map
        google={this.props.google}
        className={"map"}
        initialCenter={{ lat: 47.6205, lng: -122.3493 }}
        style={{ height: "100vh", width: "100%" }}
      >
        {this.state.updatedPlaces != null &&
          this.state.updatedPlaces.map((place, i) => (
            <Marker
              key={i}
              onClick={this.handleMarkerClick}
              position={{
                lat: parseFloat(place.latitude),
                lng: parseFloat(place.longitude)
              }}
              icon={{
                url:
                  place.offense_parent_group === "ASSAULT OFFENSES"
                    ? "http://maps.google.com/mapfiles/kml/paddle/ylw-blank.png"
                    : place.offense_parent_group ===
                      "BURGLARY/BREAKING&ENTERING"
                    ? "http://maps.google.com/mapfiles/kml/paddle/orange-blank.png"
                    : place.offense_parent_group === "TRESPASS OF REAL PROPERTY"
                    ? "http://maps.google.com/mapfiles/kml/paddle/orange-circle.png"
                    : place.offense_parent_group === "STOLEN PROPERTY OFFENSES"
                    ? "http://maps.google.com/mapfiles/kml/paddle/grn-blank.png"
                    : place.offense_parent_group === "SEX OFFENSES"
                    ? "http://maps.google.com/mapfiles/kml/paddle/wht-circle.png"
                    : place.offense_parent_group ===
                      "DESTRUCTION/DAMAGE/VANDALISM OF PROPERTY"
                    ? "http://maps.google.com/mapfiles/kml/paddle/grn-circle.png"
                    : place.offense_parent_group === "DRUG/NARCOTIC OFFENSES"
                    ? "http://maps.google.com/mapfiles/kml/paddle/wht-stars.png"
                    : place.offense_parent_group === "ROBBERY"
                    ? "http://maps.google.com/mapfiles/kml/paddle/purple-blank.png"
                    : place.offense_parent_group === "MOTOR VEHICLE THEFT "
                    ? "http://maps.google.com/mapfiles/kml/paddle/pink-blank.png"
                    : place.offense_parent_group === "HOMICIDE OFFENSES"
                    ? "http://maps.google.com/mapfiles/kml/paddle/ltblu-blank.png"
                    : place.offense_parent_group === "ARSON"
                    ? "http://maps.google.com/mapfiles/kml/paddle/blu-blank.png"
                    : place.offense_parent_group === "HUMAN TRAFFICKING"
                    ? "http://maps.google.com/mapfiles/kml/paddle/ltblu-circle.png"
                    : place.offense_parent_group === "PROSTITUTION OFFENSES"
                    ? "http://maps.google.com/mapfiles/kml/paddle/T.png"
                    : `http://maps.google.com/mapfiles/kml/pushpin/red-pushpin.png`,
                scaledSize: new window.google.maps.Size(50, 50)
              }}
              placeIndex={i}
              name={place.offense}
            />
          ))}

        <InfoWindow
          marker={this.state.activeMarker}
          visible={this.state.showingInfoWindow}
          onClose={this.handleClose}
        >
          <div>
            {" "}
            <h6>{this.state.selectedPlace.offense}</h6>
            <p> {"Crime: " + this.state.selectedPlace.offense_parent_group}</p>
            <p> {"City: " + this.state.selectedPlace.mcpp}</p>
            <p> {"Report Date: " + this.state.selectedPlace.report_datetime}</p>
            <p> {"Report Number: " + this.state.selectedPlace.report_number}</p>
          </div>
        </InfoWindow>
      </Map>
    );
  }
}

export default GoogleApiWrapper({
  apiKey: "YOUR_API_KEY"
})(MapView);
User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement