如何在React组件中加载脚本

12

我有以下的脚本文件

<script language="javascript">

document.write('<script language="javascript" src="http://tickettransaction.com/?bid='+bid+'&sitenumber='+site+'&tid=event_dropdown" ></' + 'script>');
</script>

我遵循这个在React/JSX中添加脚本标签,但对我没有用...

我该如何在我的React组件中加载脚本?


需要更多上下文信息才能解决此问题。另外,你所说的如何在我的React组件中加载脚本是什么意思? - Moti Korets
我希望你知道React使用虚拟DOM。 - Mohhamad Hasham
@AshishChoudhary 不要将它附加到 this.instance 上。尝试直接将其附加到文档中。 - digitake
尝试将URL更改为带有shttps://,看看是否有所帮助。在componentDidMount中执行document.body.appendChild时,您会得到什么错误? - Moti Korets
@AshishChoudhary,你的脚本实际上是在加载后尝试使用document.write,这是不允许的。你可能需要通过嵌入到HTML中来加载它,或者用appendChild替换脚本中的所有document.write - digitake
8个回答

18

经过大量的研究和开发,我终于找到了解决方案。

我使用了npm postscribe在React组件中加载脚本。

postscribe('#mydiv', '<script language="javascript" src="http://tickettransaction.com/?bid='+bid+'&sitenumber='+site+'&tid=event_dropdown"></script>')

3
太棒了,感谢您发布这篇文章!我曾花费比我想象中更多的时间尝试将本地 Amazon 广告加载到 React 组件中,但这个方法解决了我的问题。如果其他人也在寻找同样的内容,请将您的 componentDidMount 设置为以下内容:componentDidMount() { postScribe('#YourDivId','复制并粘贴 Amazon 代码'); } - Miek

13

使用函数组件的 2021 TypeScript 示例,可在 NextJS 中运行

(确保代码仅在客户端运行)


declare global {
  interface Window {
    hbspt: any
  }
}

export default function Contact() {
  useEffect(() => {
    if (window && document) {
      const script = document.createElement('script')
      const body = document.getElementsByTagName('body')[0]
      script.src = '//js.hsforms.net/forms/v2.js'
      body.appendChild(script)
      script.addEventListener('load', () => {
        window.hbspt.forms.create({
          // this example embeds a Hubspot form into a React app but you can tweak it for your use case
          // any code inside this 'load' listener will run after the script is appended to the page and loaded in the client
        })
      })
    }
  }, [])

  return <div id="hbspt-form" className="p-5"></div>
}

有没有办法可以跳过事件监听器“load”?比如我在父页面上添加了脚本,想在后来的子组件中为多个表单使用同一个脚本。 - Dhanendra Kumar
不太清楚你的意思,但你可以使用parentScript = document.getElementsByClassName(...)或类似的方法获取对父页面中添加的脚本的引用,然后在该引用上使用“load”事件监听器,与此处相同 - 例如parentScript.addEventListener('load', ... - Marcos

8
以下方法对我有效,尝试一下,希望也能对你有效。 基本上,您可以创建一个脚本标签并将其附加到body标签上。像这样--
var tag = document.createElement('script');
tag.async = true;
tag.src = 'THE PATH TO THE JS FILE OR A CDN LINK';
var body = document.getElementsByTagName('body')[0];
body.appendChild(tag);

你可以在React生命周期钩子中像这样使用它。
componentDidMount() {
    var loadScript = function (src) {
      var tag = document.createElement('script');
      tag.async = false;
      tag.src = src;
      var body = document.getElementsByTagName('body')[0];
      body.appendChild(tag);
    }

    loadScript('PATH TO THE JS FILE OR CDN URL');
  }

2

我推荐使用React Helmet。我在几个Create-React-Apps上使用过它,它允许你编写实际的脚本标签和纯JS结合在一起。

这使得流程更加顺畅。因此,对于您来说,一旦导入了React Helmet,它将变成以下内容:

<script language="javascript" src='http://tickettransaction.com/?bid='+ bid + '&sitenumber='+ site +'&tid=event_dropdown' ></ script>

1

作者已将此标记为“已废弃和未维护”https://www.npmjs.com/package/react-load-script - Guy Sartorelli

1

0

大多数用于完成此任务的软件包已经过时。我找到了一个解决方案,可能对某些人有用,它使用钩子来控制状态并根据其采取行动。

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

使用它就像这样简单:

const externalScript = 'https://player.live-video.net/1.6.1/amazon-ivs-player.min.js';
const scriptStatus = useExternalScript(externalScript);

useEffect(() => {
    if (scriptStatus === 'ready') {
        // Do something with it
    }
}, [scriptStatus]);

-4

2022年更新,支持基于类和函数的组件。

您可以创建以下函数,然后在componentDidMount中使用它:

function loadScript(url, callback){

    let script = document.createElement("script")
    script.type = "text/javascript";

    if (script.readyState){  //IE
        script.onreadystatechange = function(){
            if (script.readyState == "loaded" ||
                    script.readyState == "complete"){
                script.onreadystatechange = null;
                callback();
            }
        };
    } else {  //Others
        script.onload = function(){
            callback();
        };
    }

    script.src = url;
    document.getElementsByTagName("head")[0].appendChild(script);
}

// For class based components
componentDidMount() {
    loadScript("scriptUrl", callback());
}

// For functional components
useEffect(() => {
    loadScript("scriptUrl", callback());
}, [])

来源:如何将第三方JS库添加到Create React App中


1
链接往往会随着时间而改变,请避免添加链接,而是在此处发布链接的亮点作为答案。 - Technotronic
1
从"How do I write a good answer" (https://stackoverflow.com/help/how-to-answer)
鼓励提供外部资源的链接,但请在链接周围添加上下文,以便您的同行用户了解它是什么以及为什么存在。始终引用重要链接的最相关部分,以防目标站点无法访问或永久离线。
- Technotronic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接