Добавление тега script в React/JSX
У меня есть довольно простая проблема с попыткой добавить встроенный скрипт в компонент 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>
Но ни один из подходов не выполняет желаемый скрипт. Я полагаю, что я пропустил что-то простое. Может кто-то помочь с этим?
P.S. Игнорируйте "foobar", у меня на самом деле есть настоящий идентификатор, который я не хотел раскрывать.
5 ответ(ов)
Мой любимый способ - использовать 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>
);
}
};
Вы можете найти библиотеку по ссылке на GitHub.
Я попытался отредактировать принятый ответ пользователя @Alex McMillan, но у меня это не удалось. Поэтому я предлагаю отдельный ответ, в котором можно получить значение загружаемой вами библиотеки. Это очень важное отличие, о котором спрашивали, и которое мне понадобилось для реализации с использованием stripe.js.
useScript.js
import { useState, useEffect } from 'react'
export const useScript = (url, name) => {
const [lib, setLib] = useState({})
useEffect(() => {
const script = document.createElement('script')
script.src = url
script.async = true
script.onload = () => setLib({ [name]: window[name] })
document.body.appendChild(script)
return () => {
document.body.removeChild(script)
}
}, [url])
return lib
}
Использование выглядит так:
const PaymentCard = (props) => {
const { Stripe } = useScript('https://js.stripe.com/v2/', 'Stripe')
}
ПРИМЕЧАНИЕ: Сохраняя библиотеку внутри объекта, мы избегаем проблем, так как часто библиотека является функцией, и React будет вызывать эту функцию при хранении в состоянии, чтобы проверить изменения. Это может привести к сбоям в библиотеках (например, Stripe), которые ожидают, что их вызовут с определенными аргументами. Поэтому мы сохраняем это в объекте, чтобы скрыть это от React и защитить функции библиотеки от вызова.
Вы можете использовать компонент, который я создал для интеграции Typekit в React: https://github.com/coreyleelarson/react-typekit.
Вам просто нужно передать ID вашего Typekit как пропс, и всё будет работать.
Вот пример компонента:
import React from 'react';
import Typekit from 'react-typekit';
const HtmlLayout = () => (
<html>
<body>
<h1>Мой пример React компонента</h1>
<Typekit kitId="abc123" />
</body>
</html>
);
export default HtmlLayout;
Просто замените abc123
на ваш актуальный Kit ID, и это позволит вам использовать шрифты из Typekit в вашем приложении.
Вы можете использовать Range.createContextualFragment
как элегантный способ внедрения HTML-кода, включая выполнение скриптов, аналогично dangerouslySetInnerHTML
в React. Пример функции, выполняющей эту задачу:
/**
* Похож на dangerouslySetInnerHTML в React, но также выполняет JS-код.
* Использование:
* <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
. Это полезно, если вам нужно динамически добавлять HTML и выполнять скрипты в этом контексте.
Вот как я смог добавить два внешних JavaScript файла в свой код React:
Шаг 1:
Я установил React-Helmet, выполнив команду npm i react-helmet
в терминале в директории моего проекта React.
Шаг 2:
Затем я добавил следующий импорт в свой код: import { Helmet } from "react-helmet";
.
Шаг 3:
И наконец, вот как я добавил внешние JS файлы с помощью Helmet:
<Helmet>
<script src="path/to/my/js/file1.js" type="text/javascript" />
<script src="path/to/my/js/file2.js" type="text/javascript" />
</Helmet>
Таким образом, я смог успешно подключить внешние JavaScript файлы в своем приложении на React.
Как обновить вложенные свойства состояния в React
Может ли выражение (a == 1 && a == 2 && a == 3) когда-либо оцениться как истинное?
В чем разница между React Native и React?
Как реализовать дебаунс?
Обнаружена ошибка: Невозможное нарушение: Неверный тип элемента: ожидался строковый тип (для встроенных компонентов) или класс/функция, но получен объект