GAPI client sometimes not initialized correctly
Closed this issue · 4 comments
So.... the GAPI client is used for the Google OAuth sign in workflow, and for all the Google Sheets API calls.
It works like so:
In public/index.html
, we initially load the Google code through a CDN:
Lines 33 to 39 in 6fc1185
The embedded js script above should dispatch the event "google-loaded" every time the google platform code is finished loading into our app.
Then in Header.js
component, what I've done is have a useEffect(func, [])
<- empty list as second arg so it only fires once, and the function just creates an event listener for "google-loaded".
match/src/components/header/Header.js
Lines 38 to 42 in 6fc1185
If you see, the function calls handleClientLoad
, which is in util/gapi.js
:
Lines 19 to 46 in 6fc1185
This handleClientLoad
function does the initialization by triggering initClient
.
However, see in handleAuthClick
, that is where I catch if window.gapi
is not loaded, then I call an alert. Basically if the script in html did not load in correctly, then window.gapi
will not be initialized.
You should be asking: What's the point of the useEffect
? And why don't I just call window.addEventListener
from outside the React component?
The reason is, to install a callback function (take a look at the function authenticationCallback
) that can modify Recoil state, we must have access to those React hooks (we want to add the user info to Recoil state once user logs in), which means we must call handleClientLoad
from within the scope of a React component.
I am pretty sure the issue is with this weird work-around to install this callback func. I suspect that sometimes the useEffect
call is not triggered before the google cdn in index.html is finished loading, so that the handleClientLoad
doesn't get triggered, and window.gapi
is not initialized.
There is pleeenty of documentation on how to use their google-api-javascript-client.
Google something like "google api javascript client initialization" or sth
Some potential solutions here:
google/google-api-javascript-client#399
So the issue was that it would create an event listener after the gapi client has been initialized?
Yeah, not after the client had been initialized, but after the script finished loading. So the 'google-loaded' event was occurring before the event listener was created, since the file can load pretty quickly.
To test this, I added a short delay before creating the listener with
window.addEventListener("google-loaded", () => handleClientLoad(authenticationCallback));
and the issue was reproduced every time.
So, my fix was to check if the script has already loaded (and therefore the "google-loaded" event has already happened) before creating the listener. If the script has already loaded, we can just call handleClientLoad directly rather than waiting for the event:
// Check if api is already loaded
if (window.gapi) {
handleClientLoad(authenticationCallback);
} else {
// Not already loaded; create event listener
console.log("creating event listener for google-loaded")
window.addEventListener("google-loaded", () => handleClientLoad(authenticationCallback));
}
Great work!!