google is not defined
I'm implementing the Map feature in an nextjs personal project of mine.
I've imported the script on _app.js and did as the documentation demonstrates.
Although when I run the Map component the following error appears.
I've tried to workaround this issue by passing the api key inside the script tag itself but didn't work.
If you would like to upvote the priority of this issue, please comment below or react with :+1: so we can see what is popular when we triage.
@ernanni Thank you for opening this issue. 🙏 Please check out these other resources that might help you get to a resolution in the meantime:
- Check the issue tracker - bugs and feature requests for Google Maps Platform APIs and SDKs
- Open a support case - Get 1:1 support in Cloud Console.
- Discord - chat with other developers
-
StackOverflow - use the
google-mapstag
This is an automated message, feel free to ignore.
Have you tried window.google?
What seemed to work for me is
this lib just loads google script, but for example google.maps.marker.AdvancedElement is not loaded before google maps init, so sometimes there is race condition with can not read AdvancedElement of undefined
The solution
create global Event, which is called after google map is initiated
if (typeof window !== 'undefined') {
const mapsLoaded = new Event('googleMapsLoaded')
// @ts-ignore
window.initGoogleMap = () => {
window.dispatchEvent(mapsLoaded)
}
}
import useLoadExternalScript, {
TScriptStatus as ScriptLoadingStatus,
} from '@ui/hooks/useLoadExternalScript'
import { useEffect, useState } from 'react'
const useLoadGoogleMaps = (apiKey: string) => {
const scriptStatus = useLoadExternalScript(
`https://maps.googleapis.com/maps/api/js?key=${apiKey}&v=beta&libraries=places,marker&callback=initGoogleMap`
)
const [status, setStatus] = useState<ScriptLoadingStatus>(scriptStatus)
// set status ready after google maps init
useEffect(() => {
const afterInit = () => setStatus('ready')
if (status !== 'ready') {
window.addEventListener('googleMapsLoaded', afterInit)
}
return () => {
window.removeEventListener('googleMapsLoaded', afterInit)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [setStatus])
// set status error
useEffect(() => {
if (status !== 'ready') {
setStatus(scriptStatus)
}
}, [scriptStatus, setStatus, status])
return status
}
export default useLoadGoogleMaps
Caveat
there is possibly next race condition, if the script loads faster and sets the status to ready, the status is already 'ready' and there is the same issue, but I don't care anymore, because it would take me too much time to handle it, if you have solution, please provide, I am ready to improve my code
What this LIb is missing
you have to handle loading the script only once yourself, I thought this lib will provide exactly this functionality, instead I implemented that on my own and I am loading all the libs at once because of this, I would appreciate, if I just could use this and it would solve all those details. I don't see any benefits in using this lib