UNPKG

3.42 kBTypeScriptView Raw
1/* eslint-disable filenames/match-regex */
2import * as React from 'react'
3import invariant from 'invariant'
4
5import { isBrowser } from './utils/isbrowser'
6import { injectScript } from './utils/injectscript'
7import { preventGoogleFonts } from './utils/prevent-google-fonts'
8import { makeLoadScriptUrl, LoadScriptUrlOptions } from './utils/make-load-script-url'
9
10import { defaultLoadScriptProps } from './LoadScript'
11
12export interface UseLoadScriptOptions extends LoadScriptUrlOptions {
13 id?: string
14 preventGoogleFontsLoading?: boolean
15}
16
17let previouslyLoadedUrl: string
18
19export function useLoadScript({
20 id = defaultLoadScriptProps.id,
21 version = defaultLoadScriptProps.version,
22 googleMapsApiKey,
23 googleMapsClientId,
24 language,
25 region,
26 libraries,
27 preventGoogleFontsLoading,
28 channel,
29}: UseLoadScriptOptions): {
30 isLoaded: boolean
31 loadError: Error | undefined
32 url: string
33} {
34 const isMounted = React.useRef(false)
35 const [isLoaded, setLoaded] = React.useState(false)
36 const [loadError, setLoadError] = React.useState<Error | undefined>(undefined)
37
38 React.useEffect(function trackMountedState() {
39 isMounted.current = true
40 return (): void => {
41 isMounted.current = false
42 }
43 }, [])
44
45 React.useEffect(
46 function applyPreventGoogleFonts() {
47 if (isBrowser && preventGoogleFontsLoading) {
48 preventGoogleFonts()
49 }
50 },
51 [preventGoogleFontsLoading]
52 )
53
54 React.useEffect(
55 function validateLoadedState() {
56 if (isLoaded) {
57 invariant(
58 !!window.google,
59 'useLoadScript was marked as loaded, but window.google is not present. Something went wrong.'
60 )
61 }
62 },
63 [isLoaded]
64 )
65
66 const url = makeLoadScriptUrl({
67 version,
68 googleMapsApiKey,
69 googleMapsClientId,
70 language,
71 region,
72 libraries,
73 channel,
74 })
75
76 React.useEffect(
77 function loadScriptAndModifyLoadedState() {
78 if (!isBrowser) {
79 return
80 }
81
82 function setLoadedIfMounted(): void {
83 if (isMounted.current) {
84 setLoaded(true)
85 previouslyLoadedUrl = url
86 }
87 }
88
89 if (window.google && previouslyLoadedUrl === url) {
90 setLoadedIfMounted()
91 return
92 }
93
94 injectScript({ id, url })
95 .then(setLoadedIfMounted)
96 .catch(function handleInjectError(err) {
97 if (isMounted.current) {
98 setLoadError(err)
99 }
100 console.warn(`
101 There has been an Error with loading Google Maps API script, please check that you provided correct google API key (${googleMapsApiKey ||
102 '-'}) or Client ID (${googleMapsClientId || '-'})
103 Otherwise it is a Network issue.
104 `)
105 console.error(err)
106 })
107 },
108 [id, url]
109 )
110
111 const prevLibraries = React.useRef<undefined | string[]>()
112
113 React.useEffect(
114 function checkPerformance() {
115 if (prevLibraries.current && libraries !== prevLibraries.current) {
116 console.warn(
117 'Performance warning! LoadScript has been reloaded unintentionally! You should not pass `libraries` prop as new array. Please keep an array of libraries as static class property for Components and PureComponents, or just a const variable outside of component, or somewhere in config files or ENV variables'
118 )
119 }
120 prevLibraries.current = libraries
121 },
122 [libraries]
123 )
124
125 return { isLoaded, loadError, url }
126}