/google-maps-react-markers

Google Maps library that accepts markers as react components and works with React 18+.

Primary LanguageJavaScriptMIT LicenseMIT

Google Maps React Markers

NPM NPM total downloads Maintained GitHub license: MIT GitHub stars GitHub open issues PRs welcome

Google Maps library that accepts markers as react components and works with React 18+.

It supports a small set of the props of Google Map React. Clustering also is possible. The library implements Google Maps Custom Overlays official library.

If you like this library, please consider supporting me ❤️

Buy me a Coffee PayPal

🚀 Demo

See it in action here (API KEY not provided).

Demo source code is available here.

🛠 Install

pnpm add google-maps-react-markers

or

yarn add google-maps-react-markers

or

npm install --save google-maps-react-markers

💻 Usage

const App = () => {
  const mapRef = useRef(null)
  const [mapReady, setMapReady] = useState(false)

  /**
   * @description This function is called when the map is ready
   * @param {Object} map - reference to the map instance
   * @param {Object} maps - reference to the maps library
   */
  const onGoogleApiLoaded = ({ map, maps }) => {
    mapRef.current = map
    setMapReady(true)
  }

  const onMarkerClick = (e, { markerId, lat, lng }) => {
    console.log('This is ->', markerId)

    // inside the map instance you can call any google maps method
    mapRef.current.setCenter({ lat, lng })
    // rif. https://developers.google.com/maps/documentation/javascript/reference?hl=it
  }

  return (
    <>
      {mapReady && <div>Map is ready. See for logs in developer console.</div>}
      <GoogleMap
        apiKey=""
        defaultCenter={{ lat: 45.4046987, lng: 12.2472504 }}
        defaultZoom={5}
        options={mapOptions}
        mapMinHeight="100vh"
        onGoogleApiLoaded={onGoogleApiLoaded}
        onChange={(map) => console.log('Map moved', map)}
      >
        {coordinates.map(({ lat, lng, name }, index) => (
          <Marker
            key={index}
            lat={lat}
            lng={lng}
            markerId={name}
            onClick={onMarkerClick}
            // draggable={true}
            // onDragStart={(e, { latLng }) => {}}
            // onDrag={(e, { latLng }) => {}}
            // onDragEnd={(e, { latLng }) => {}}
          />
        ))}
      </GoogleMap>
    </>
  )
}

export default App

🧐 Props

GoogleMap component

Prop Type Required Default Description
apiKey string yes '' API Key to load Google Maps
defaultCenter object yes { lat: 0, lng: 0 } Default center of the map
defaultZoom number yes 1-20 Default zoom of the map
libraries array no ['places', 'geometry'] Libraries to load
options object no {} Options for the map
onGoogleApiLoaded function no () => {} Callback when the map is loaded
onChange function no () => {} Callback when the map has changed
events array no [] Array of objects name/handler of DOM events to pass down to the div overlay. Example: events: [{ name: 'onClick', handler: () => {} }]
children node no null Markers of the map
loadScriptExternally bool no false Whether to load the Google Maps script externally.
If true, the status prop is required and it will be used to control the loading of the script
status string no idle The forced status of the Google Maps script. Depends on loadScriptExternally.
It can be one of idle, loading, ready, error
loadingContent node no 'Google Maps is loading' Content to show while the map is loading
idleContent node no 'Google Maps is on idle' Content to show when the map is idle
errorContent node no 'Google Maps is on error' Content to show when the map has an error
mapMinHeight string no 'unset' Min height of the map
containerProps object no {} Props for the div container of the map
scriptCallback function no () => {} window global callback passed to the Google Script
externalApiParams object no undefined Optional params to pass to the Google API script. Eg. {region: 'IT', language: 'it'}

Markers

Prop Type Required Default Description
lat number yes undefined Latitude of the marker
lng number yes undefined Longitude of the marker
draggable bool no false If true, the marker can be dragged
onDragStart func no () => {} This event is fired when the user starts dragging the marker
onDrag func no () => {} This event is repeatedly fired while the user drags the marker
onDragEnd func no () => {} This event is fired when the user stops dragging the marker

📍 Clustering

For clustering, follow this guide using useSupercluster Hook, but use bounds in this way:

const onMapChange = ({ bounds, zoom }) => {
  const ne = bounds.getNorthEast()
  const sw = bounds.getSouthWest()
  /**
   * useSupercluster accepts bounds in the form of [westLng, southLat, eastLng, northLat]
   * const { clusters, supercluster } = useSupercluster({
   *	points: points,
   *	bounds: mapBounds.bounds,
   *	zoom: mapBounds.zoom,
   * })
   */
  setMapBounds({ ...mapBounds, bounds: [sw.lng(), sw.lat(), ne.lng(), ne.lat()], zoom })
}

👥 Contributing

To run the project locally, clone the repo and run:

yarn install
yarn dev
# in another tab
cd docs
yarn install
yarn dev

Do your changes to src/ or docs/src directory, commits all files (ones in dist too) and open a PR.

💻 Built with

🗒 License

MIT © giorgiabosello

🙏 Support

Buy me a Coffee PayPal


Developed with ❤️ in Italy 🇮🇹