通过 react-helmet 添加脚本标签时如何忽略 TypeScript 错误?

How can I ignore TypeScript errors when adding script tags via react-helmet?

以下 tsx 代码生成 TypeScript 错误。 //@ts-ignore 无效。

<Helmet>
  <script>
    (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
    new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
    j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
    'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
    })(window,document,'script','dataLayer','GTM-*******');
  </script>
</Helmet>

以下代码有效,但我想使用子 <script> 标签与 script 组件 属性.

<Helmet
  script={[
    {
      type: 'application/javascript',
      innerHTML: '(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({\'gtm.start\':new Date().getTime(),event:\'gtm.js\'});var f=d.getElementsByTagName(s)[0],j=d.createElement(s),dl=l!=\'dataLayer\'?\'&l=\'+l:\'\';j.async=true;j.src=\'https://www.googletagmanager.com/gtm.js?id=\'+i+dl;f.parentNode.insertBefore(j,f);})(window,document,\'script\',\'dataLayer\',\'GTM-*******\');'
    }
  ]}
/>

此脚本是否必须作为组件堆的一部分嵌入?

我在使用 YouTube 的 iframe API 时遇到了类似的问题,解决方案是创建脚本元素并引用存在后创建的 javascript 对象(如果您需要这样做,请查看就像你真的只是想导入一些 JS)。除非有我想要管理的视觉元素,否则我不需要为此创建一个反应组件。

// GoogleTagManager.ts

export class GoogleTagManager {
  someVariable: someVariableType = null 

  constructor () {
    const script: HTMLScriptElement = <HTMLScriptElement>document.createElement('script')

    script.src = '[URL_TO_JS_FILE]'

    script.onload = (): void => console.log('loaded google tag manager')

    document.body.appendChild(script)
  }

  WaitForVariable (): void {
    let timeout: number

    const OnTimeout = (): void => {
      if (timeout) {
        clearTimeout(timeout)
      }

      if (typeof [TARGET_VARIABLE] !== 'undefined') {
        this.someVariable = [TARGET_VARIABLE]
        return
      }

      timeout = setTimeout(OnTimeout, 1000)
    }
  }
}

如果你想显示一些信息,那么你可以把它变成一个 React 组件,并将构造函数逻辑移动到 componentDidMount。或者我会考虑将任何结果数据发送到商店并有一个单独的组件来呈现结果数据。

谨慎起见,您可以像这样使用 dangerouslySetInnerHTML


<script
  dangerouslySetInnerHTML={{
    __html: `
    (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
    new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
    j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
    'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
    })(window,document,'script','dataLayer','GTM-*******');
`,
  }}
/>

但要小心cross-site scripting (XSS) attacks

感谢 https://github.com/nfl/react-helmet/issues/334#issuecomment-413319383 解决了这个问题。

<Helmet>
  <script>
    {`
      alert('BOOM');
    `} 
  </script>
</Helmet>