Skip to content

Commit dec6133

Browse files
authored
fix: check status of loading google oauth script (#313)
1 parent 0ca216e commit dec6133

File tree

2 files changed

+58
-3
lines changed

2 files changed

+58
-3
lines changed

ui/public/index.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
<script>
1919
window.GOOGLE_CLIENT_ID = "REPLACE_GOOGLE_CLIENT_ID";
2020
</script>
21-
<script src="https://accounts.google.com/gsi/client" async defer></script>
2221
<!--
2322
Notice the use of %PUBLIC_URL% in the tags above.
2423
It will be replaced with the URL of the `public` folder during the build.

ui/src/pages/login.tsx

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useEffect, useState } from "react";
1+
import React, { useEffect, useState, useRef } from "react";
22

33
import Avatar from "@mui/material/Avatar";
44
import CssBaseline from "@mui/material/CssBaseline";
@@ -42,12 +42,68 @@ function Copyright(props: any) {
4242

4343
const theme = createTheme();
4444

45+
// useLoadGsiScript from
46+
// https://github.com/MomenSherif/react-oauth/blob/244d2b970d910af18a1bfdf2a74625834e087b40/packages/%40react-oauth/google/src/GoogleOAuthProvider.tsx
47+
interface UseLoadGsiScriptOptions {
48+
/**
49+
* Nonce applied to GSI script tag. Propagates to GSI's inline style tag
50+
*/
51+
nonce?: string;
52+
/**
53+
* Callback fires on load [gsi](https://accounts.google.com/gsi/client) script success
54+
*/
55+
onScriptLoadSuccess?: () => void;
56+
/**
57+
* Callback fires on load [gsi](https://accounts.google.com/gsi/client) script failure
58+
*/
59+
onScriptLoadError?: () => void;
60+
}
61+
62+
function useLoadGsiScript(options: UseLoadGsiScriptOptions = {}): boolean {
63+
const { nonce, onScriptLoadSuccess, onScriptLoadError } = options;
64+
65+
const [scriptLoadedSuccessfully, setScriptLoadedSuccessfully] =
66+
useState(false);
67+
68+
const onScriptLoadSuccessRef = useRef(onScriptLoadSuccess);
69+
onScriptLoadSuccessRef.current = onScriptLoadSuccess;
70+
71+
const onScriptLoadErrorRef = useRef(onScriptLoadError);
72+
onScriptLoadErrorRef.current = onScriptLoadError;
73+
74+
useEffect(() => {
75+
const scriptTag = document.createElement("script");
76+
scriptTag.src = "https://accounts.google.com/gsi/client";
77+
scriptTag.async = true;
78+
scriptTag.defer = true;
79+
scriptTag.nonce = nonce;
80+
scriptTag.onload = () => {
81+
setScriptLoadedSuccessfully(true);
82+
onScriptLoadSuccessRef.current?.();
83+
};
84+
scriptTag.onerror = () => {
85+
setScriptLoadedSuccessfully(false);
86+
onScriptLoadErrorRef.current?.();
87+
};
88+
89+
document.body.appendChild(scriptTag);
90+
91+
return () => {
92+
document.body.removeChild(scriptTag);
93+
};
94+
}, [nonce]);
95+
96+
return scriptLoadedSuccessfully;
97+
}
98+
4599
declare var google: any;
46100

47101
export function GoogleSignin() {
48102
const { handleGoogle } = useAuth();
103+
const scriptLoadedSuccessfully = useLoadGsiScript();
49104

50105
useEffect(() => {
106+
if (!scriptLoadedSuccessfully) return;
51107
console.log("nodeenv", process.env.NODE_ENV);
52108
let client_id =
53109
process.env.NODE_ENV === "development"
@@ -62,7 +118,7 @@ export function GoogleSignin() {
62118
document.getElementById("googleLoginDiv"),
63119
{ theme: "outline", size: "large" } // customization attributes
64120
);
65-
}, [handleGoogle]);
121+
}, [handleGoogle, scriptLoadedSuccessfully]);
66122
return <Box id="googleLoginDiv"></Box>;
67123
}
68124

0 commit comments

Comments
 (0)