Javascript 将脚本标签添加到 React/JSX
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/34424845/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Adding script tag to React/JSX
提问by ArrayKnight
I have a relatively straightforward issue of trying to add inline scripting to a React component. What I have so far:
我有一个相对简单的问题,即尝试向 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>
);
}
};
I have also tried:
我也试过:
<script src="https://use.typekit.net/foobar.js"></script>
<script>try{Typekit.load({ async: true });}catch(e){}</script>
Neither approach seems to execute the desired script. I'm guessing it's a simple thing I'm missing. Can anybody help out?
这两种方法似乎都没有执行所需的脚本。我猜这是我错过的一件简单的事情。有人可以帮忙吗?
PS: Ignore the foobar, I have a real id actually in use that I didn't feel like sharing.
PS:忽略 foobar,我有一个真正在使用的真实 id,我不想分享。
回答by Alex McMillan
Edit: Things change fast and this is outdated - see update
编辑:事情变化很快,这已经过时了 - 请参阅更新
Do you want to fetch and execute the script again and again, every time this component is rendered, or just once when this component is mounted into the DOM?
你想一次又一次地获取和执行脚本,每次渲染这个组件时,还是当这个组件被挂载到 DOM 时才一次?
Perhaps try something like this:
也许尝试这样的事情:
componentDidMount () {
const script = document.createElement("script");
script.src = "https://use.typekit.net/foobar.js";
script.async = true;
document.body.appendChild(script);
}
However, this is only really helpful if the script you want to load isn't available as a module/package. First, I would always:
但是,这仅在您要加载的脚本不能作为模块/包使用时才真正有用。首先,我总是:
- Look for the package on npm
- Download and install the package in my project (
npm install typekit
) import
the package where I need it (import Typekit from 'typekit';
)
- 在npm上查找包
- 在我的项目中下载并安装包 (
npm install typekit
) import
我需要的包裹 (import Typekit from 'typekit';
)
This is likely how you installed the packages react
and react-document-title
from your example, and there is a Typekit package available on npm.
这可能是你如何安装的软件包react
,并react-document-title
从你的榜样,并有一个在NPM提供Typekit包。
Update:
更新:
Now that we have hooks, a better approach might be to use useEffect
like so:
现在我们有了钩子,更好的方法可能是useEffect
像这样使用:
useEffect(() => {
const script = document.createElement('script');
script.src = "https://use.typekit.net/foobar.js";
script.async = true;
document.body.appendChild(script);
return () => {
document.body.removeChild(script);
}
}, []);
Which makes it a great candidate for a custom hook (eg: hooks/useScript.js
):
这使它成为自定义钩子的绝佳候选者(例如:)hooks/useScript.js
:
import { useEffect } from 'react';
const useScript = url => {
useEffect(() => {
const script = document.createElement('script');
script.src = url;
script.async = true;
document.body.appendChild(script);
return () => {
document.body.removeChild(script);
}
}, [url]);
};
export default useScript;
Which can be used like so:
可以这样使用:
import useScript from 'hooks/useScript';
const MyComponent = props => {
useScript('https://use.typekit.net/foobar.js');
// rest of your component
}
回答by sidonaldson
Further to the answers above you can do this:
除了上面的答案,您还可以这样做:
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)} />;
}
}
The div is bound to this
and the script is injected into it.
div 被绑定,this
脚本被注入其中。
Demo can be found on codesandbox.io
可以在codeandbox.io上找到演示
回答by AC Patrice
My favorite way is to use React Helmet – it's a component that allows for easy manipulation of the document head in a way you're probably already used to.
我最喜欢的方法是使用 React Helmet——它是一个组件,允许以您可能已经习惯的方式轻松操作文档头。
e.g.
例如
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>
);
}
};
回答by scabbiaza
If you need to have <script>
block in SSR (server-side rendering), an approach with componentDidMount
will not work.
如果您需要<script>
在 SSR(服务器端渲染)中使用块,则使用 的方法componentDidMount
将不起作用。
You can use react-safe
library instead.
The code in React will be:
您可以改用react-safe
库。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>
回答by jake2620
The answer Alex Mcmillanprovided helped me the most but didn't quite work for a more complex script tag.
Alex Mcmillan提供的答案对我帮助最大,但对于更复杂的脚本标签却不太适用。
I slightly tweaked his answer to come up with a solution for a long tag with various functions that was additionally already setting "src".
我稍微调整了他的答案,为具有各种功能的长标签提出了一个解决方案,这些功能另外已经设置了“src”。
(For my use case the script needed to live in head which is reflected here as well):
(对于我的用例,脚本需要存在于头脑中,这也反映在此处):
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);
}
回答by Corey Larson
I created a React component for this specific case: https://github.com/coreyleelarson/react-typekit
我为这个特定案例创建了一个 React 组件:https: //github.com/coreyleelarson/react-typekit
Just need to pass in your Typekit Kit ID as a prop and you're good to go.
只需将您的 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;
回答by Maximilian Hils
There is a very nice workaround using Range.createContextualFragment
.
有一个非常好的解决方法,使用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));
}
This works for arbitrary HTML and also retains context information such as document.currentScript
.
这适用于任意 HTML 并保留上下文信息,例如document.currentScript
.
回答by Ashh
You can use npm postscribe
to load script in react component
您可以使用npm postscribe
在反应组件中加载脚本
postscribe('#mydiv', '<script src="https://use.typekit.net/foobar.js"></script>')
回答by Muhammad Usama Rabani
You can also use react helmet
您也可以使用反应头盔
import React from "react";
import {Helmet} from "react-helmet";
class Application extends React.Component {
render () {
return (
<div className="application">
<Helmet>
<meta charSet="utf-8" />
<title>My Title</title>
<link rel="canonical" href="http://example.com/example" />
<script src="/path/to/resource.js" type="text/javascript" />
</Helmet>
...
</div>
);
}
};
Helmet takes plain HTML tags and outputs plain HTML tags. It's dead simple, and React beginner friendly.
Helmet 采用纯 HTML 标签并输出纯 HTML 标签。它非常简单,而且 React 初学者友好。
回答by ben
for multiple scripts, use this
对于多个脚本,使用这个
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')