J'ai un problème relativement simple d'essayer d'ajouter un script inline à un composant React. Ce que j'ai jusqu'ici:
'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>
);
}
};
J'ai aussi essayé:
<script src="https://use.typekit.net/foobar.js"></script>
<script>try{Typekit.load({ async: true });}catch(e){}</script>
Aucune approche ne semble exécuter le script souhaité. Je suppose que c'est une chose simple qui me manque. Quelqu'un peut-il aider?
PS: Ignorez la foobar, j'ai un identifiant réellement utilisé que je n'avais pas envie de partager.
Voulez-vous extraire et exécuter le script encore et encore, chaque fois que ce composant est rendu, ou juste une fois lorsque ce composant est monté dans le DOM?
Peut-être essayer quelque chose comme ça:
componentDidMount () {
const script = document.createElement("script");
script.src = "https://use.typekit.net/foobar.js";
script.async = true;
document.body.appendChild(script);
}
Cependant, cela n’est vraiment utile que si le script que vous voulez charger n’est pas disponible en tant que module/package. D'abord, je voudrais toujours:
npm install typekit
)import
le paquet où j'en ai besoin (import Typekit from 'typekit';
)C'est probablement ainsi que vous avez installé les packages react
et react-document-title
à partir de votre exemple. Il existe un package Typekit disponible sur npm .
En plus des réponses ci-dessus, vous pouvez le faire:
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)} />;
}
}
Le div est lié à this
et le script y est injecté.
La démo peut être trouvée sur codesandbox.io
Ma méthode préférée consiste à utiliser React Helmet - il s'agit d'un composant qui permet de manipuler facilement la tête du document d'une manière à laquelle vous êtes probablement déjà habitué.
par exemple.
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>
);
}
};
La réponse Alex Mcmillan fournie m'aide le plus, mais ne fonctionne pas tout à fait pour une balise de script plus complexe.
J'ai légèrement modifié sa réponse pour trouver une solution pour une longue balise avec diverses fonctions qui mettait déjà déjà "src".
(Pour mon cas d'utilisation, le script avait besoin de vivre en tête, ce qui est reflété ici aussi):
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);
}
Si vous devez avoir un bloc _<script>
_ en SSR (rendu côté serveur), une approche avec componentDidMount
ne fonctionnera pas.
Vous pouvez utiliser la bibliothèque react-safe
à la place. Le code dans React sera:
_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>
_
J'ai créé un composant React _ pour ce cas particulier: https://github.com/coreyleelarson/react-typekit
Il vous suffit de passer votre ID de kit Typekit comme accessoire et vous êtes prêt à partir.
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;
Il existe une solution très agréable utilisant 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));
}
Cela fonctionne pour du HTML arbitraire et conserve également des informations de contexte telles que document.currentScript
.
Vous pouvez utiliser npm postscribe
pour charger le script dans le composant de réaction
_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);
}
pour plusieurs scripts, utilisez cette
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')
J'ai essayé toutes les solutions proposées mais aucune ne fonctionne. J'essaie d'intégrer cela à un composant mais il ne se charge pas. c'est une bannière de 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>
J'ai document "undefined"
lors de l'actualisation. Alors j'ai essayé de cette façon
const MyComponent = () => {
let script = React.createElement("script", {
src: "https://.....js path",
async: true,
defer: true,
crossorigin: "anonymous"
})
return (
<div>
{script}
</div>)
}