Add An External Script to a Vue Component
Tags: vue, javascript, asynchronous, webdev
Published: 2022-01-19 18:40:01

Yesterday I tweeted this question out to the world:

{% twitter 1483547709738995714 %}

Only one person liked it. Maybe Twitter isn't the best forum for that question. Or maybe the character limit made it unclear what I meant. Or maybe I don't have enough followers for the tweet to get any traction....

I thought it was a good question though.

Here's the question worded more clearly:

**How would you go about bringing in a script from a third-party into a Vue component? And then making sure the script is there before performing logic on something brought in by the script?** 

I was able to do this one way, but I'm curious if there are other approaches.

Here's an example scenario and my solution.

## Scenario: Load Google Recaptcha API and Perform Action if API has Loaded

This is an example for the sake of showing how to do this, but it could be applied to anytime you need to load a JS script into your component and wait until after it has loaded to perform some action.

The example is a Recaptcha checkmark to verify that the user is not a robot.

![Recaptcha Checkmark](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qj4nytmuvjgmp81ugmy1.png)

### Step 1: Load the Script in the setup function

First, create a script element using Vanilla JS `document.createElement` and `setAttribute` with "src" set to the script source url. Then use `appendChild` to append that element do the document head.:

```js
export default {

  setup() {
    const recaptchaScript = document.createElement("script");
    recaptchaScript.setAttribute(
      "src",
      "https://www.google.com/recaptcha/api.js"
    );
    document.head.appendChild(recaptchaScript);
}
```
In Vue 3, the `setup` function runs before anything else, so we can create the `script` element at the very start of the component lifecycle. That ensures the script is there as soon as possible.

In Vue 2, this would be equivalent to building out the `script` element in the `create` lifecycle hook. There is a [stack overflow question](https://stackoverflow.com/questions/48693664/defer-execution-until-external-script-has-loaded-in-vue-js) that shows how to do this in Vue 2. 

### Step 2: Use setInterval to check that the script has fully loaded

Create a variable to keep track of the state of the script being loaded. Set it to false to start.

```js
let recaptchaScriptIsReady = false;
```

Write a function using setInterval to continuously run, checking that the script is loaded:

```js
 let checkInterval = setInterval(function () {
      if (grecaptcha) {
        recaptchaScriptIsReady = true;
        clearInterval(checkInterval);
        grecaptcha.ready(function () {
          grecaptcha.render("g-recaptcha", {
            sitekey: "YOUR API KEY",
          });
        });
      }
      return recaptchaScriptIsReady;
    }, 500);
```

Notice that inside the function, the `clearInterval` takes in the named function `checkInterval`, which stops the `setInterval` from continuing to run. Here's the line of code I'm talking about:

```js
 clearInterval(checkInterval);
```

So basically, to solve this problem, I create the variable `recaptchaScriptIsReady` to track the state of the script that is loading, then use the if-check to make sure the script is now there, set the `recaptchaScriptIsReady` to `true` which now opens the gate to allowing the next part of the code to run, the code that is dependent upon the original script being loaded.

Do you have a different way to do this? I would be really interested to know! Please tell me in the comments!

And please follow me on [Twitter](https://twitter.com/sandra_rodgers_)! I hope this post was helpful to someone.

Recaptcha resource: https://developers.google.com/recaptcha