DEV Community

Teerasak Vichadee
Teerasak Vichadee

Posted on

Idea on refactor GoogleMap component

Code:

import { useRef, useEffect, useState } from 'react'
import { Wrapper } from '@googlemaps/react-wrapper'

const GoogleMap = ({ center, zoom, libraries = [], onLoad }) => {
  const ref = useRef()
  const [googleMap, setGoogleMap] = useState(null)

  const handleCallback = (status, loader) => {
    loader.load().then((google) => {
      setGoogleMap(google.maps)
    })
  }

  const initMap = () => {
    return new googleMap.Map(ref.current, {
      center,
      zoom,
    })
  }

  useEffect(() => {
    if (googleMap) {
      const map = initMap()

      const services = {}
      libraries.forEach((library) => {
        console.log('looping...')
        services[library] = new googleMap.places.PlacesService(map) // use services mapping, but I'm too lazy to do that right now
      })

      onLoad &&
        onLoad({
          map,
          ...services,
        })
    }
  }, [googleMap])

  return (
    <Wrapper apiKey="" libraries={libraries} callback={handleCallback}>
      <div
        ref={ref}
        style={{ width: '100%', height: '950px', margin: '0 auto' }}
      >
        This is map
      </div>
    </Wrapper>
  )
}

function App() {
  const center = { lat: 34.0430058, lng: -118.2673597 }
  const zoom = 12

  const handleMapLoaded = (services) => {
    services.places.nearbySearch(
      {
        location: center,
        radius: '500',
        type: ['restaurant'],
      },
      (results, status) => {
        console.log('status:', status)
        console.log('results:', results)
      }
    )
  }

  return (
    <div>
      <GoogleMap
        center={center}
        zoom={zoom}
        libraries={['places']}
        onLoad={handleMapLoaded}
      />
    </div>
  )
}

export default App
Enter fullscreen mode Exit fullscreen mode

Why?

  • I don't want to use global variable like windows.google, look lame for me
  • It's look plugable, just put library that it support, it will load and return object
  • Expose logic of another service, for example nearby places and don't have to put in GoogleMap component anymore

Improvement

  • Map marker can render as prop
  • More advance component can render as child

Discussion (0)