question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Custom Marker as a component.

See original GitHub issue

I have multiple views and on different views I have different maps, however, I need to display user location on every map, I decided to turn it into reusable component that would watch user location and update it when necessery as well as only return the Marker.

An example of a map code

import React from 'react';
import {Map, InfoWindow, Marker, GoogleApiWrapper} from 'google-maps-react';
import apiKey from './maps-api-key.js';
import UserLocation from '../shared-components/user-location.jsx';

const styles = {
  map: {
    maxWidth: '85%',
    margin: '5% auto 0'
  },
  container: {
    minHeight: '400px',
    maxHeight: '800px',
    height: '70%'
  }
};

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

  onMarkerClick(props, marker) {
    this.setState({
      selectedPlace: props,
      activeMarker: marker,
      showingInfoWindow: true
    });
  }

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

  render() {
    const {google, coord, desc, title} = this.props;
    const {onMapClicked, onMarkerClick} = this;
    const {activeMarker, showingInfoWindow} = this.state;
    return (
      <Map
        style={styles.map}
        containerStyle={styles.container}
        className="super-map-wrapper"
        google={google}
        initialCenter={coord}
        onClick={onMapClicked.bind(this)}
        zoom={13}>

        <Marker
          visible={true}
          onClick={onMarkerClick.bind(this)}
          title={desc}
          name={title} />

        <InfoWindow
          marker={activeMarker}
          visible={showingInfoWindow}>
          <div style={{maxWidth:'40vw'}}>
            <h2>{title}</h2>
            <p>{desc}</p>
          </div>
        </InfoWindow>

        <UserLocation/>

      </Map>
    );
  }
}

export default GoogleApiWrapper(apiKey)(SingleMarkerMap);

and the contents of user-location.jsx

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

const defaultLocation = {
  lng: 2.1663020364940166,
  lat: 41.382491852864234
};

export class UserLocation extends React.Component {
  constructor() {
    super();
    this.state = {
      coord: {},
      visible: false
    };
  }

  updateLocation(pos) {
    let blueDot = {
      url: '/img/map/bluedot.png',
    };
    if ('google' in window) {
      blueDot.size = new google.maps.Size(32, 32);
      blueDot.origin = new google.maps.Point(0, 0);
      blueDot.anchor = new google.maps.Point(8, 8);
      blueDot.scaledSize = new google.maps.Size(16, 16);
    }
    this.setState({
      coord: {
        lat: pos.coords.latitude,
        lng: pos.coords.longitude
      },
      visible: true,
      icon: blueDot
    });
  }

  onErrorGettingLocation(err) {
    console.log('error getting location', err);
  }

  componentWillMount() {
    let gl = navigator.geolocation;
    const glOptions = {
      enableHighAccuracy: true,
      timeout: 15000,
      maximumAge: 0
    };
    gl.watchPosition(
      this.updateLocation.bind(this),
      this.onErrorGettingLocation.bind(this),
      glOptions
    );
  }

  render() {
    let {visible, coord, icon} = this.state;

    return visible ?
      <Marker
        position={defaultLocation}
        icon={icon}
        title="Your location"
        name="marker name" /> :
	  null;
  }
}

export default UserLocation;

With logging I can see that the user location component is mounted and updates, however the icon does not appear on the map.

If I write the userLocation as a simple Marker directly inside the Map I am able to see the dot. Code example below

import React from 'react';
import {Map, InfoWindow, Marker, GoogleApiWrapper} from 'google-maps-react';
import apiKey from './maps-api-key.js';

const styles = {
  map: {
    maxWidth: '85%',
    margin: '5% auto 0'
  },
  container: {
    minHeight: '400px',
    maxHeight: '800px',
    height: '70%'
  }
};

export class SingleMarkerMap extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      showingInfoWindow: false,
      activeMarker: {},
      selectedPlace: {},
      visible: false,
      userLocationCoord: {}
    };
  }

  onMarkerClick(props, marker) {
    this.setState({
      selectedPlace: props,
      activeMarker: marker,
      showingInfoWindow: true
    });
  }

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

  // start from user location

  updateLocation(pos) {
    let blueDot = {
      url: '/img/map/bluedot.png',
    };
    if ('google' in window) {
      blueDot.size = new google.maps.Size(32, 32);
      blueDot.origin = new google.maps.Point(0, 0);
      blueDot.anchor = new google.maps.Point(8, 8);
      blueDot.scaledSize = new google.maps.Size(16, 16);
    }
    this.setState({
      userLocationCoord: {
        lat: pos.coords.latitude,
        lng: pos.coords.longitude
      },
      visible: true,
      icon: blueDot
    });
  }

  onErrorGettingLocation(err) {
    console.log('error getting location', err);
  }

  componentWillMount() {
    let gl = navigator.geolocation;
    const glOptions = {
      enableHighAccuracy: true,
      timeout: 15000,
      maximumAge: 0
    };
    gl.watchPosition(
      this.updateLocation.bind(this),
      this.onErrorGettingLocation.bind(this),
      glOptions
    );
  }

  // end from user location

  render() {
    const {google, coord, desc, title} = this.props;
    const {onMapClicked, onMarkerClick} = this;
    const {
      activeMarker,
      showingInfoWindow,
      visible,
      userLocationCoord,
      icon
    } = this.state;
    return (
      <Map
        style={styles.map}
        containerStyle={styles.container}
        className="super-map-wrapper"
        google={google}
        initialCenter={coord}
        onClick={onMapClicked.bind(this)}
        zoom={13}>

        <Marker
          visible={true}
          onClick={onMarkerClick.bind(this)}
          title={desc}
          name={title} />

        <InfoWindow
          marker={activeMarker}
          visible={showingInfoWindow}>
          <div style={{maxWidth:'40vw'}}>
            <h2>{title}</h2>
            <p>{desc}</p>
          </div>
        </InfoWindow>

        {
          visible ?
            <Marker
              position={userLocationCoord}
              icon={icon}
              title="marker title"
              name="marker name" /> :
            null
        }

      </Map>
    );
  }
}

export default GoogleApiWrapper(apiKey)(SingleMarkerMap);

Is there something I am missing here or the Marker component cannot be inside standard react components?

Thank you

Issue Analytics

  • State:open
  • Created 6 years ago
  • Reactions:6
  • Comments:6

github_iconTop GitHub Comments

5reactions
michealpetersonacommented, Mar 8, 2018

The Marker component can’t be rendered inside another component since the map does not render its children in the traditional manner. You can get around this by returning the JSX directly to where you need it by calling the render function on a React component or by using a function as I did below.

const CustomMarker = (props) => {
    return(
        <Marker position={props.location}/>
    );
}
render(){
        return (
            <Map google={this.props.google} zoom={10} initialCenter={{lat: 40.7484, lng: -73.9857}}>
                {CustomMarker({location: {lat: 40.7484, lng: -73.9857}})}
            </Map>
        );
    }
}

This issue should remain open though since the original approach is the React way of doing it…

4reactions
fullmoon6661commented, Oct 17, 2018

From this https://github.com/fullstackreact/google-maps-react/issues/51 I found that explicitly pass the props from the parent actually work In your case, it would be something like

<UserLocation {...this.props}/>

and in the user-location.jsx should be like

render() {
    let {visible, coord, icon} = this.state;
    return visible ?
    <Marker
        {...this.props}
        position={defaultLocation}
        icon={icon}
        title="Your location"
        name="marker name" /> :
    null;
}

I’m not sure if this is the right way of doing it

Read more comments on GitHub >

github_iconTop Results From Across the Web

Custom Marker as a React Component with react-google ...
Instead of the default Google Maps markers, balloons and other map components, you can render your cool animated react components on the map....
Read more >
Google Maps and React With a Custom Marker
Google Map React is a component wrapping a set of the Google Maps API ... Now we will create a custom marker instead...
Read more >
Building A Custom Google Maps Marker ... - Daw-Chih Liou
We will be building a proof of concept to create customer Google Maps markers using any React component in a Next.js project.
Read more >
CustomMarker | React InstantSearch - Algolia
This component is an alternative to <Marker /> . In some cases, you may want to have the full control of the marker...
Read more >
Custom Markers | Maps JavaScript API - Google Developers
Adds the icon property to the MarkerOptions object, to change the marker's icon. The icon property can be either a string (the URL...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found