Saher Elgendy
Saher Elgendy

Reputation: 1619

Why markers not filtered correctly?

I am trying to create a map with locations fetched from Foursquare API , the locations are displayed in two ways in the app, as a side bar containing a list items (location names) and markers on the map, there is a search box, and depending on the query on this search box data should be filtered so the locations and markers should be filtered to match the query in the same time, now i got the location list filtered correctly but not the markers on the map

here is the parent component

import React, { Component } from 'react';
import Map from './Map';
import List from './List'
import escapeRegExp from 'escape-string- 
regexp';
import './App.css';

class App extends Component {
  state = {
  places: [],
  query: '',
}

componentDidMount() {
  this.fetchPlaces();
}

fetchPlaces() {
  const client_id =  "N4UIDVOE5XA3YVMBMMLIANAYLDEGSTDJY3KLFM0BAQJB1A4G" ;
  const client_secret = "RVWSHIZAAKLLTW03ELYCPVY1GJ1QZ312AP0C1MLOCBP5JG4Q";

  const api = "https://api.foursquare.com";
  const request =  fetch(`${api}/v2/venues/search?ll=30.044281,31.224291&categoryId=4bf58dd8d48988d181941735,4bf58dd8d48988d181941735,4bf58dd8d48988d13a941735&client_id=${client_id}&client_secret=${client_secret}&v=20180719`);

  return request.then(response => {
  //MDN
    const myOk = response.ok;

    if(myOk) {
      return response.json();
    } 
   }).then(places => {
   this.setState({places: places.response.venues});
   //on error fetching locations   
   }).catch(() => alert('error fetching data'));


   }

updateQuery = (query) => {
   this.setState({query})
}

render() {
  const { places, query} = this.state;
  let placesToShow;

  if(query) {
    const match = new RegExp(escapeRegExp(query), 'i');
    placesToShow = places.filter(place => match.test(place.name));
  }
  else {
    placesToShow = places;
  }

 return (
   <div className="app">
     <Map places={ placesToShow }/>
     <List places ={ placesToShow } 
     onUpdateQuery={ this.updateQuery }/>
   </div>
 );
}

}

export default App;

and this is the child component

import React, { Component } from 'react';

class Map extends Component {

componentDidMount() {
  //getting the script of the map
  const script = document.getElementsByTagName('script')[0];
  //load the map after the script loads
  script.addEventListener('load', e => {this.initMap()}); 
}

initMap() {
  const container = document.getElementById('map');

  const map = new 
  window.google.maps.Map(container, {
    center: { lat: 30.044281, lng: 31.224291 }, 
  });

  this.setState({ map });

}


createMarkers() {
  const { map } = this.state;

  const markers = 
     this.props.places.map(place => {  return (new  window.google.maps.Marker({     
       position: {lat: place.location.lat, lng: place.location.lng},
       name: place.name,
       map: map, 
    }));
 })

 const bounds = new window.google.maps.LatLngBounds();

 const largeInfoWindow = new window.google.maps.InfoWindow();


 markers.forEach(marker => {
   bounds.extend(marker.position);

   marker.addListener('click', e => {
    largeInfoWindow.setContent(`<div>${marker.name }</div>`);
   largeInfoWindow.open(map, marker);
  });

})

map.fitBounds(bounds);
}

componentDidUpdate() {
   this.createMarkers(); 
}

render(){
   return(
    <div id="map" />
  );
 }
}

export default Map;

so why markers are not filtered correctly, and how to achieve that???

Edit

It worked after i set all markers map to null before adding only the filtered ones

componentDidUpdate(prevProps, prevState) {
  if(prevProps.places !== this.props.places) {
    this.state.markers.forEach(marker => marker.setMap(null))
    this.createMarkers(); 
  }
}

Upvotes: 0

Views: 172

Answers (1)

Tyler
Tyler

Reputation: 2390

I think the issue is that your createMarkers function does not remove markers. It only appends new markers and probably duplicates them as well. The easy thing to do would be to remove all markers at the start of createMarkers using marker.setMap(null) as described here. This isn't the most efficient solution, however, as you could compare the previous markers with the new markers and only adjust as necessary. Alternatively, you could utilize the react-google-maps library to handle the markers for you.

Upvotes: 2

Related Questions