React useScript Hook

ReactReactBeginner
Practice Now

This tutorial is from open-source community. Access the source code

Introduction

In this lab, we will learn how to use the useScript hook in React to dynamically load an external script. This hook can be used to efficiently handle the loading and unloading of scripts, and it can be especially useful when working with third-party libraries or APIs. By the end of this lab, you will be able to use the useScript hook to load external scripts in your React applications.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL react(("`React`")) -.-> react/FundamentalsGroup(["`Fundamentals`"]) react(("`React`")) -.-> react/AdvancedConceptsGroup(["`Advanced Concepts`"]) react(("`React`")) -.-> react/StateManagementGroup(["`State Management`"]) react/FundamentalsGroup -.-> react/jsx("`JSX`") react/AdvancedConceptsGroup -.-> react/hooks("`React Hooks`") react/StateManagementGroup -.-> react/use_state_reducer("`Using useState and useReducer`") subgraph Lab Skills react/jsx -.-> lab-38406{{"`React useScript Hook`"}} react/hooks -.-> lab-38406{{"`React useScript Hook`"}} react/use_state_reducer -.-> lab-38406{{"`React useScript Hook`"}} end

React useScript Hook

index.html and script.js have already been provided in the VM. In general, you only need to add code to script.js and style.css.

To dynamically load an external script, use the useState() hook to create a state variable that stores the load status of the script. Next, use the useEffect() hook to handle all the logic for loading and unloading the script anytime the src changes. If no src value is present, set the status to 'idle' and return. Use Document.querySelector() to check if a <script> element with the appropriate src value exists. If no relevant element exists, use Document.createElement() to create one and give it the appropriate attributes. Use the data-status attribute as a way to indicate the status of the script, setting it to 'loading' initially. If a relevant element exists, skip initialization and update the status from its data-status attribute. This ensures that no duplicate element will be created. Use EventTarget.addEventListener() to listen for 'load' and 'error' events and handle them by updating the data-status attribute and the status state variable. Finally, when the component unmounts, use Document.removeEventListener() to remove any listeners bound to the element.

Here's an example implementation of the useScript hook:

const useScript = (src) => {
  const [status, setStatus] = React.useState(src ? "loading" : "idle");

  React.useEffect(() => {
    if (!src) {
      setStatus("idle");
      return;
    }

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

    if (!script) {
      script = document.createElement("script");
      script.src = src;
      script.async = true;
      script.setAttribute("data-status", "loading");
      document.body.appendChild(script);

      const setDataStatus = (event) => {
        script.setAttribute(
          "data-status",
          event.type === "load" ? "ready" : "error"
        );
      };
      script.addEventListener("load", setDataStatus);
      script.addEventListener("error", setDataStatus);
    } else {
      setStatus(script.getAttribute("data-status"));
    }

    const setStateStatus = (event) => {
      setStatus(event.type === "load" ? "ready" : "error");
    };

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

    return () => {
      if (script) {
        script.removeEventListener("load", setStateStatus);
        script.removeEventListener("error", setStateStatus);
      }
    };
  }, [src]);

  return status;
};

Here's an example usage of the useScript hook:

const script =
  "data:text/plain;charset=utf-8;base64,KGZ1bmN0aW9uKCl7IGNvbnNvbGUubG9nKCdIZWxsbycpIH0pKCk7";

const Child = () => {
  const status = useScript(script);
  return <p>Child status: {status}</p>;
};

const MyApp = () => {
  const status = useScript(script);
  return (
    <>
      <p>Parent status: {status}</p>
      <Child />
    </>
  );
};

ReactDOM.createRoot(document.getElementById("root")).render(<MyApp />);

Please click on 'Go Live' in the bottom right corner to run the web service on port 8080. Then, you can refresh the Web 8080 Tab to preview the web page.

Summary

Congratulations! You have completed the React useScript Hook lab. You can practice more labs in LabEx to improve your skills.

Other React Tutorials you may like