Dynamically load Google Scripts with React and the useEffect Hook
As an alumnus of Flatiron School, I scan one of their channels daily to help out those following in my tracks. Many folks are taking advantage of their online self-paced program, and while the flexibility is invaluable, I’ve seen more than a few students spinning their wheels when left to their own devices.
A few days ago, a student was trying to access a Google Books API immediately on page load and was getting errors that the functions they expected to be attached to the window object were undefined.
These errors can be damning to solve for a novice, as one ponders if they’ve entered the <script> tag incorrectly, or if they have are missing authorization keys. The problem is actually that while external JS scripts from Google load very quickly, they don’t quite load that fast.
The developer had dutifully entered the appropriate <script> tag in their root HTML file, but I offered an elegant solution to add that tag at runtime.
To add a <script> tag at runtime, we can dust off some vanilla JS to add it to the DOM. After adding the tag, we can attach a listener for the ‘load’ event of the script tag and then know it’s okay to move forward with accessing the functions. To ensure we only add the script tag once, let’s leverage the useEffect hook at the root level of our component tree, with an empty array ( [ ] ) as a dependency. Using an empty array as a dependency will ensure we don’t execute the hook again, even if other code forces a re-render of our root component.
Even if using a global state manager like Redux or my preference, MobX, using local state can keep things simple, so useState is the right call here.
Recall from the outset that the developer wanted to load info from the Google Books API on page load. We can’t quite accomplish that, as the script tag needs to load, but we can come pretty damn close by loading info as soon as possible.
Thankfully, we can call hooks multiple times in the same component, so another use of useEffect works beautifully here, this time passing our boolean that tracks script loading as a dependency.
Note the use above of escaping from the function if the script is not loaded yet, which will be the case when the hook first executes on component render. I wired up a simple text display of the value for the student to visualize. If your eyes are fast enough, you’d catch the initial text display of ‘Script not loaded’ before it quickly changes to ‘Script loaded’ once Google’s CDN loads it into your browser.
useEffect, useState, and a lot of the more “straightforward” Hooks might seem simple, but they can be combined in very powerful ways. The next time you’re having trouble synchronizing state in your application, just remember….. The Hooookkkkks bring you backkkkk!!