Agregar etiqueta de script a React/JSX
Tengo un problema relativamente sencillo al intentar agregar secuencias de comandos en línea a un componente de 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 probado:
<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 lo que me falta. ¿Alguien puede ayudar?
PD: ignora la barra de menú, tengo una identificación real en uso que no tenía ganas de compartir.
Editar: las cosas cambian rápidamente y esto está desactualizado; ver actualización
¿Quiere recuperar y ejecutar el script una y otra vez, cada vez que se procesa 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 sólo es realmente útil si el script que desea cargar no está disponible como módulo/paquete. Primero, siempre haría:
- Busque el paquete en npm
- Descargar e instalar el paquete en mi proyecto (
npm install typekit
) import
el paquete donde lo necesito (import Typekit from 'typekit';
)
Probablemente así es como instaló los paquetes react
y react-document-title
según su ejemplo, y hay un paquete Typekit disponible en npm .
Actualizar:
Ahora que tenemos ganchos, un mejor enfoque podría ser usarlos useEffect
así:
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);
}
}, []);
Lo que lo convierte en un gran candidato para un gancho personalizado (por ejemplo:) 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;
Que se puede utilizar así:
import useScript from 'hooks/useScript';
const MyComponent = props => {
useScript('https://use.typekit.net/foobar.js');
// rest of your component
}
Mi forma favorita es usar React Helmet: es un componente que permite una fácil manipulación del cabezal del documento de una manera a la 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>
);
}
};
https://github.com/nfl/react-helmet
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 this
y el script se inyecta en él.
La demostración se puede encontrar en codesandbox.io
Esta respuesta explica el por qué detrás de este comportamiento.
Cualquier método para representar la script
etiqueta no funciona como se esperaba:
- Usando la
script
etiqueta para scripts externos - Usando
dangerouslySetInnerHTML
Por qué
React DOM (el renderizador de reaccionar en la web) utiliza createElement
llamadas para representar JSX en elementos DOM.
createElement
utiliza la innerHTML
API DOM para finalmente agregarlos al DOM ( consulte el código en la fuente de React ). innerHTML
no ejecutascript
la etiqueta agregada como consideración de seguridad. Y esta es la razón por la que, a su vez, la representación de script
etiquetas en React no funciona como se esperaba.
Para saber cómo usar script
etiquetas en React, consulte otras respuestas en esta página.
Si necesita tener <script>
un bloqueo en SSR (renderizado del lado del servidor), un enfoque componentDidMount
no funcionará.
Puedes usar react-safe
la biblioteca en su lugar. 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>