circuit

How to Dynamically Load Scripts in React




Adding a script to the website is the common requirement. Let's suppose that the website is using some external tools. To use it properly, you will have to use external JavaScript. pretty straightforward requirement, huh?

You can add script two ways — static way, just add the script tag index.html.

But there is some pitfalls in this way such as:

  • It will increase the loading time for the website, thus affecting the website's performance.

  • Script will load on other pages which don't use the external script at all.

  • You don't have much control over when/how the script will load and execute.

Another way is to load the script is to load it dynamically.

Benefits of loading script dynamically

Some of the benefits are:

  • You can load script on that page on which is it really required

  • It will reduce the page initial loading time

  • You can have a fallback UI till the script is being loaded. It will improve make the user experience better.

  • Easy and clean code

Using hook for loading it dynamically

Since our website is in React, I am going to use hooks for loading script dynamically.

useExternalScript.js:

import { useEffect, useState } from "react";

export const useExternalScript = (url) => {
  let [state, setState] = useState(url ? "loading" : "idle");

  useEffect(() => {
    if (!url) {
      setState("idle");
      return;
     }

    let script = document.querySelector(`script[src="${url}"]`);

    const handleScript = (e) => {
      setState(e.type === "load" ? "ready" : "error");
    };

    if (!script) {
      script = document.createElement("script");
      script.type = "application/javascript";
      script.src = url;
      script.async = true;
      document.body.appendChild(script);
      script.addEventListener("load", handleScript);
      script.addEventListener("error", handleScript);
    }

   script.addEventListener("load", handleScript);
   script.addEventListener("error", handleScript);

   return () => {
     script.removeEventListener("load", handleScript);
     script.removeEventListener("error", handleScript);
   };
  }, [url]);

  return state;
};

The above block has code that is required to use the external script. First, it will check that if the script tag is already present or not. If yes, it's adding the event listeners for events load and error

If the script tag is not present already, it will create a script tag, set its src and other properties, and append it to the body. load and error event listeners are also added.

Here, you can see that out of the hook is state which is a string. There are 4 possible outputs which are — loading, idle , load and error .

Now our useExternalScript the hook is ready. Now, let's use it in the component.

Usage of useExternalScript hook

Let's suppose the component:

Demo:

import React from "react";
import { useExternalScript } from "./hooks/useExternalScript";
import { ComponentWithScript } from "./ComponentWithScript";

export const Demo = () => {
  const externalScript = "*<external-script-url>*";
  const state = useExternalScript(externalScript);
  return (
    <div>
     {state === "loading" && <p>Loading...</p>}
     {state === "ready" && <ComponentWithScript />}
    </div>
  );
};

In the above component, you can see that the corresponding UI is being loaded based upon the state's value.

Here is a working example:

And that's it! I hope you have enjoyed reading this article and have found it useful. Be sure to let us know your thoughts in the comments.




Continue Learning