javascript - props - Agregar etiqueta de script a React/JSX
reactjs setstate (13)
¿Desea buscar y ejecutar el script una y otra vez, cada vez que se representa este componente, o solo una vez cuando este componente se monta en el DOM?
Quizás intente algo como esto:
componentDidMount () {
const script = document.createElement("script");
script.src = "https://use.typekit.net/foobar.js";
script.async = true;
document.body.appendChild(script);
}
Sin embargo, esto solo es realmente útil si el script que desea cargar no está disponible como módulo / paquete. Primero, siempre:
- Busque el paquete en npm
-
Descargue e instale el paquete en mi proyecto (
npm install typekit
) -
import
el paquete donde lo necesito (import Typekit from ''typekit'';
)
Esta es probablemente la forma en que instaló los paquetes
react
y
react-document-title
de su ejemplo, y hay un
paquete Typekit disponible en npm
.
Tengo un problema relativamente sencillo al tratar de agregar secuencias de comandos en línea a un componente React. Lo que tengo hasta ahora:
''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>
);
}
};
También he intentado:
<script src="https://use.typekit.net/foobar.js"></script>
<script>try{Typekit.load({ async: true });}catch(e){}</script>
Ninguno de los enfoques parece ejecutar el script deseado. Supongo que es algo simple que me estoy perdiendo. ¿Alguien puede ayudar?
PD: Ignora el foobar, tengo una identificación real realmente en uso que no tenía ganas de compartir.
Además de las respuestas anteriores, puede hacer esto:
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)} />;
}
}
El div está vinculado a
this
y el script se inyecta en él.
La demostración se puede encontrar en codesandbox.io
Creé un componente React para este caso específico: https://github.com/coreyleelarson/react-typekit
Solo necesita pasar su ID de Kit Typekit como accesorio y ya está listo.
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;
Hay una muy buena solución usando
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));
}
Esto funciona para HTML arbitrario y también retiene información de contexto como
document.currentScript
.
Intenté todas las soluciones propuestas pero ninguna funciona. Estoy intentando incrustar esto en un componente pero no se está cargando. Este es un banner de bannersnack.com .
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'')
La respuesta que proporcionó me ayudó más, pero no funcionó para una etiqueta de script más compleja.
Modifiqué ligeramente su respuesta para encontrar una solución para una etiqueta larga con varias funciones que además ya estaba configurando "src".
(Para mi caso de uso, el script necesitaba vivir en la cabeza, lo que también se refleja aquí):
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);
}
La solución depende del escenario. Como en mi caso, tuve que cargar una incrustación de calor dentro de un componente de reacción.
Calendly busca un div y lee su atributo
data-url
y carga un iframe dentro de dicho div.
Todo está bien cuando carga la página por primera vez: primero, se representa div con
data-url
.
Luego, el script calendly se agrega al cuerpo.
El navegador lo descarga y lo evalúa y todos volvemos felices a casa.
El problema surge cuando navegas y luego vuelves a la página. Esta vez, el script todavía está en el cuerpo y el navegador no lo vuelve a descargar ni a evaluar.
Reparar:
-
En
componentWillUnmount
busque y elimine el elemento de script. Luego, en el montaje, repita los pasos anteriores. -
Ingrese
$.getScript
. Es un ingenioso asistente de jquery que toma un URI de script y una devolución de llamada exitosa. Una vez que el script se cargó, lo evalúa y dispara su devolución de llamada exitosa. Todo lo que tengo que hacer es en micomponentDidMount
$.getScript(url)
. Mi método derender
ya tiene el div calendly. Y funciona sin problemas.
Mi forma favorita es usar React Helmet: es un componente que permite una fácil manipulación del cabezal del documento de una manera que probablemente ya esté acostumbrado.
p.ej
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>
);
}
};
Puede encontrar la mejor respuesta en el siguiente enlace:
const loadDynamicScript = (callback) => { const existingScript = document.getElementById(''scriptId''); if (!existingScript) { const script = document.createElement(''script''); script.src = ''url''; // URL for the third-party library being loaded. script.id = ''libraryName''; // eg, googleMaps or stripe document.body.appendChild(script); script.onload = () => { if (callback) callback(); }; } if (existingScript && callback) callback(); };
Puede usar
npm postscribe
para cargar el script en el componente react
postscribe(''#mydiv'', ''<script src="https://use.typekit.net/foobar.js"></script>'')
Si necesita tener bloque
<script>
en SSR (representación del lado del servidor), un enfoque con
componentDidMount
no funcionará.
En su lugar, puede usar la biblioteca
react-safe
.
El código en React será:
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>
para múltiples scripts, use esto
const MyComponent = () => {
let script = React.createElement("script", {
src: "https://.....js path",
async: true,
defer: true,
crossorigin: "anonymous"
})
return (
<div>
{script}
</div>)
}
<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>