React useScript 钩子

ReactReactBeginner
立即练习

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

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

简介

在本实验中,我们将学习如何在 React 中使用 useScript 钩子来动态加载外部脚本。这个钩子可用于高效地处理脚本的加载和卸载,在使用第三方库或 API 时特别有用。完成本实验后,你将能够在 React 应用程序中使用 useScript 钩子来加载外部脚本。


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 钩子"}} react/hooks -.-> lab-38406{{"React useScript 钩子"}} react/use_state_reducer -.-> lab-38406{{"React useScript 钩子"}} end

React useScript 钩子

虚拟机中已提供 index.htmlscript.js。一般来说,你只需在 script.jsstyle.css 中添加代码。

要动态加载外部脚本,请使用 useState() 钩子创建一个状态变量,用于存储脚本的加载状态。接下来,使用 useEffect() 钩子在 src 发生变化时处理加载和卸载脚本的所有逻辑。如果没有 src 值,将 status 设置为 'idle' 并返回。使用 Document.querySelector() 检查是否存在具有适当 src 值的 <script> 元素。如果不存在相关元素,则使用 Document.createElement() 创建一个并赋予其适当的属性。使用 data-status 属性来指示脚本的状态,初始时将其设置为 'loading'。如果存在相关元素,则跳过初始化并根据其 data-status 属性更新 status。这可确保不会创建重复的元素。使用 EventTarget.addEventListener() 监听 'load''error' 事件,并通过更新 data-status 属性和 status 状态变量来处理它们。最后,当组件卸载时,使用 Document.removeEventListener() 移除绑定到该元素的任何监听器。

以下是 useScript 钩子的示例实现:

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;
};

以下是 useScript 钩子的示例用法:

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 />);

请点击右下角的“Go Live”以在端口 8080 上运行 Web 服务。然后,你可以刷新“Web 8080”标签页来预览网页。

总结

恭喜你!你已完成 React useScript 钩子实验。你可以在 LabEx 中练习更多实验来提升你的技能。