私はインラインスクリプトを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を持っています。
このコンポーネントがレンダリングされるたびに、またはこのコンポーネントがDOMにマウントされたときに1回だけ、スクリプトを繰り返し取得して実行しますか?
おそらくこのようなことを試してください:
componentDidMount () {
const script = document.createElement("script");
script.src = "https://use.typekit.net/foobar.js";
script.async = true;
document.body.appendChild(script);
}
しかしながら、これはあなたがロードしたいスクリプトがモジュール/パッケージとして利用できない場合にのみ本当に役に立ちます。まず最初に、
npm install typekit
)import
必要な場所のパッケージ(import Typekit from 'typekit';
)これはおそらくあなたの例からパッケージreact
とreact-document-title
をインストールした方法であり、 npmで利用可能なTypekitパッケージ があります。
上記の回答に加えて、これを行うことができます。
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 にあります。
私のお気に入りの方法は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>
);
}
};
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>
私はこの特定のケースのために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;
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);
}
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
などのコンテキスト情報も保持します。
npm postscribe
を使用して反応コンポーネントにスクリプトをロードすることができます。
postscribe('#mydiv', '<script src="https://use.typekit.net/foobar.js"></script>')
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);
}
複数のスクリプトの場合は、これを使用してください。
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')
提案されたすべてのソリューションを試しましたが、どれも機能しませんでした。これをコンポーネントに埋め込もうとしていますが、ロードしていません。これは 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>
更新時にdocument "undefined"
を取得しました。だから私はこのようにしてみました
const MyComponent = () => {
let script = React.createElement("script", {
src: "https://.....js path",
async: true,
defer: true,
crossorigin: "anonymous"
})
return (
<div>
{script}
</div>)
}