fullstackreact / google-maps-react

Companion code to the "How to Write a Google Maps React Component" Tutorial
https://www.fullstackreact.com/articles/how-to-write-a-google-maps-react-component/
MIT License
1.64k stars 819 forks source link

Beginner - Accessing the Markers outside of creation #209

Open natesct opened 6 years ago

natesct commented 6 years ago

Hi

Thanks for the effort, I am just struggling after reading through your texts and googling how to solve an issue.

My Map displays all my markers and I even have a text search where it filters the map locations.

However, how would I access a Marker outside of the return.

E.g. I would like to select a location from my text list - which works and filters the map. It then passes the location to a method as a parameter.
In this method I want to say

Marker with ID say equal to 1, whose 'name' = 'expected name' .. click this Marker... or Highlight this Marker.

Is this possible at all?

`return (

  <div className="container">

    <ListPlaces
      locations={this.state.locations}
      filterLocationsArray={this.filterLocationsArray}
      onLocationListItemClicked={this.onLocationListItemClicked}
    />

    <div id="map">

      <Map google={this.props.google}
        onClick={this.onMapClicked}
        zoom={14}
        style={style}
        initialCenter={{ // Cape Town
          lat: 33.9386219,
          lng: 18.2214081
        }}
        bounds={bounds}
      >

        {
          // Displays Markers for Each Location
        }

        {this.state.locations.map((location) => {

          return <Marker
            name={location.title}
            onClick={this.onMarkerClick}
            position={{ lat: location.location.lat, lng: location.location.lng }}
            key={Math.random(100)}
            id={location.id}
          />
        }
        )}

        {
          // InfoWindow for the Active Marker
        }
        <InfoWindow
          marker={this.state.activeMarker}
          onClose={this.onInfoWindowClose}
          visible={this.state.showingInfoWindow}>
          <div>
            <h1>{this.state.selectedPlace.name}</h1>
          </div>
        </InfoWindow>

      </Map>

    </div>

  </div>

)`
auser commented 6 years ago

@natesct can you create a codesandbox to demonstrate the issue?

muslimcentral commented 6 years ago

ended up using another lib

ciroque commented 6 years ago

@muslimcentral which library did you end up using? I too would like to add / remove Markers dynamically which seems to be not practical with this library...

auser commented 6 years ago

It should just create markers based on the DOM tree... what’s the problem?

Can you create a code sandbox?

muslimcentral commented 6 years ago

const ref = window.document.getElementsByTagName("script")[0] const script = window.document.createElement("script") script.src = src script.async = true ref.parentNode.insertBefore(script, ref)

I found this instead and worked for me

rbahumi commented 6 years ago

Hi All, I have created a hacky solution for this issue using inheritance. @auser please take a look and let me know you think. Am I doing something wrong here? (I am using Javascript again after many long years of python...)

import React from 'react';
import {Marker} from 'google-maps-react';
import PropTypes from 'prop-types';

/*
This class extends google-maps-react::Marker by adding two props events to the marker object:

  - onMarkerAdd: callback that is called when a new google.maps.Marker object is added to the map
  - onMarkerRemove: callback that is called when a new google.maps.Marker object is removed from the map
*/
class RefMarker extends Marker{
  componentDidUpdate(prevProps) {
    if ((this.props.map !== prevProps.map) ||
      (this.props.position !== prevProps.position) ||
      (this.props.icon !== prevProps.icon)) {
        this.unsetMarker()
        this.renderMarker();
    }
  }

  componentWillUnmount() {
    this.unsetMarker()
  }

  unsetMarker(){
    if (this.marker) {
      this.marker.setMap(null);
      if (this.props.onMarkerRemove){
        this.props.onMarkerRemove(this.marker)
      }
    }
  }

  renderMarker(){
    super.renderMarker();
    if (this.marker && this.props.onMarkerAdd && this.marker.map){
      this.props.onMarkerAdd(this.marker);
    }
  }
}

RefMarker.propTypes['onMarkerAdd'] = PropTypes.func;
RefMarker.propTypes['onMarkerRemove'] = PropTypes.func;

export default RefMarker;

And this is an example of the map container which holds the list of marker in its state:

export class MapContainer extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      markersArray: [],
    }
    this.onMarkerAdd = this.onMarkerAdd.bind(this);
    this.onMarkerRemove = this.onMarkerRemove.bind(this);
  }

  onMarkerAdd(marker){
    const markersArray = this.state.markersArray
    markersArray.push(marker);
    this.setState({markersArray: markersArray});
  }

  onMarkerRemove(marker){
    const markersArray = this.state.markersArray.filter((m) => { return m !== marker; });
    this.setState({markersArray: markersArray});
  }
  render(){
    ....
  }
feemcgill commented 5 years ago

REFS! https://github.com/fullstackreact/google-maps-react/issues/186