web-dev-qa-db-ja.com

React/JSXにスクリプトタグを追加する

私はインラインスクリプトをReactコンポーネントに追加しようとするという比較的簡単な問題を抱えています。私がこれまでに持っているもの:

'use strict';

import '../../styles/pages/people.scss';

import React, { Component } from 'react';
import DocumentTitle from 'react-document-title';

import { prefix } from '../../core/util';

export default class extends Component {
    render() {
        return (
            <DocumentTitle title="People">
                <article className={[prefix('people'), prefix('people', 'index')].join(' ')}>
                    <h1 className="tk-brandon-grotesque">People</h1>

                    <script src="https://use.typekit.net/foobar.js"></script>
                    <script dangerouslySetInnerHTML={{__html: 'try{Typekit.load({ async: true });}catch(e){}'}}></script>
                </article>
            </DocumentTitle>
        );
    }
};

私も試してみました:

<script src="https://use.typekit.net/foobar.js"></script>
<script>try{Typekit.load({ async: true });}catch(e){}</script>

どちらの方法でも目的のスクリプトが実行されるとは思われません。私はそれが私が欠けている簡単なことだと思います。誰かが手伝ってくれる?

シモンズ:愚か者を無視し、私は共有する気がしなかったことを実際に使用中の本当のIDを持っています。

156
ArrayKnight

このコンポーネントがレンダリングされるたびに、またはこのコンポーネントがDOMにマウントされたときに1回だけ、スクリプトを繰り返し取得して実行しますか?

おそらくこのようなことを試してください:

componentDidMount () {
    const script = document.createElement("script");

    script.src = "https://use.typekit.net/foobar.js";
    script.async = true;

    document.body.appendChild(script);
}

しかしながら、これはあなたがロードしたいスクリプトがモジュール/パッケージとして利用できない場合にのみ本当に役に立ちます。まず最初に、

  • npm でパッケージを探してください
  • 自分のプロジェクトにパッケージをダウンロードしてインストールします(npm install typekit
  • import必要な場所のパッケージ(import Typekit from 'typekit';

これはおそらくあなたの例からパッケージreactreact-document-titleをインストールした方法であり、 npmで利用可能なTypekitパッケージ があります。

225
Alex McMillan

上記の回答に加えて、これを行うことができます。

import React from 'react';

export default class Test extends React.Component {
  constructor(props) {
    super(props);
  }

  componentDidMount() {
    const s = document.createElement('script');
    s.type = 'text/javascript';
    s.async = true;
    s.innerHTML = "document.write('This is output by document.write()!')";
    this.instance.appendChild(s);
  }

  render() {
    return <div ref={el => (this.instance = el)} />;
  }
}

Divはthisにバインドされ、スクリプトがそこに挿入されます。

デモは codesandbox.io にあります。

35
sidonaldson

私のお気に入りの方法はReact Helmetを使うことです - それはあなたがおそらく既に慣れている方法でドキュメントヘッドの簡単な操作を可能にするコンポーネントです。

例えば.

import React from "react";
import {Helmet} from "react-helmet";

class Application extends React.Component {
  render () {
    return (
        <div className="application">
            <Helmet>
                <script src="https://use.typekit.net/foobar.js"></script>
                <script>try{Typekit.load({ async: true });}catch(e){}</script>
            </Helmet>
            ...
        </div>
    );
  }
};

https://github.com/nfl/react-helmet

24
Patrice Wrex

SSR(サーバー側レンダリング)で<script>ブロックを使用する必要がある場合は、componentDidMountを使用したアプローチは機能しません。

代わりに react-safe libraryを使用できます。 Reactのコードは次のようになります。

import Safe from "react-safe"

// in render 
<Safe.script src="https://use.typekit.net/foobar.js"></Safe.script>
<Safe.script>{
  `try{Typekit.load({ async: true });}catch(e){}`
}
</Safe.script>
9
scabbiaza

私はこの特定のケースのためにReactコンポーネントを作成しました: https://github.com/coreyleelarson/react-typekit

Typekit Kit IDを支柱として渡すだけでいいのです。

import React from 'react';
import Typekit from 'react-typekit';

const HtmlLayout = () => (
  <html>
    <body>
      <h1>My Example React Component</h1>
      <Typekit kitId="abc123" />
    </body>
  </html>
);

export default HtmlLayout;
7
Corey Larson

Alex Mcmillan という回答が私を最も助けてくれましたが、もっと複雑なスクリプトタグではうまくいきませんでした。

私は彼の答えを少し微調整して、すでに "src"をすでに設定していたさまざまな機能を持つ長いタグの解決策を考え出しました。

(私のユースケースでは、スクリプトは頭の中で動く必要があり、これもここに反映されています):

  componentWillMount () {
      const script = document.createElement("script");

      const scriptText = document.createTextNode("complex script with functions i.e. everything that would go inside the script tags");

      script.appendChild(scriptText);
      document.head.appendChild(script);
  }
6
jake2620

Range.createContextualFragmentを使ったとてもいい回避策があります。

/**
 * Like React's dangerouslySetInnerHTML, but also with JS evaluation.
 * Usage:
 *   <div ref={setDangerousHtml.bind(null, html)}/>
 */
function setDangerousHtml(html, el) {
    if(el === null) return;
    const range = document.createRange();
    range.selectNodeContents(el);
    range.deleteContents();
    el.appendChild(range.createContextualFragment(html));
}

これは任意のHTMLに対して機能し、document.currentScriptなどのコンテキスト情報も保持します。

2
Maximilian Hils

npm postscribe を使用して反応コンポーネントにスクリプトをロードすることができます。

postscribe('#mydiv', '<script src="https://use.typekit.net/foobar.js"></script>')
2
Anthony Winzlet
componentDidMount() {
  const head = document.querySelector("head");
  const script = document.createElement("script");
  script.setAttribute(
    "src",
    "https://assets.calendly.com/assets/external/widget.js"
  );
  head.appendChild(script);
}
0
Marlcg58

複数のスクリプトの場合は、これを使用してください。

var loadScript = function(src) {
  var tag = document.createElement('script');
  tag.async = false;
  tag.src = src;
  document.getElementsByTagName('body').appendChild(tag);
}
loadScript('//cdnjs.com/some/library.js')
loadScript('//cdnjs.com/some/other/library.js')
0
ben

提案されたすべてのソリューションを試しましたが、どれも機能しませんでした。これをコンポーネントに埋め込もうとしていますが、ロードしていません。これは bannersnack.com からのバナーです。

<script type="text/javascript">
var bannersnack_embed = {"hash":"bxpien9pr","width":1190,"height":300,"t":1559889975,"userId":39254375,"responsive":true,"type":"html5"};
</script>
<script type="text/javascript" src="//cdn.bannersnack.com/iframe/embed.js"></script>
0
Charm

更新時にdocument "undefined"を取得しました。だから私はこのようにしてみました

const MyComponent = () => {
   let script = React.createElement("script", {
    src: "https://.....js path",
    async: true,
    defer: true,
    crossorigin: "anonymous"
})

return (

        <div>
            {script}
        </div>)
}
0
Asanka