5

Добавление тега script в React/JSX

16

У меня есть довольно простая проблема с попыткой добавить встроенный скрипт в компонент 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 ответ(ов)

1

Мой любимый способ - использовать 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.

0

Я попытался отредактировать принятый ответ пользователя @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 и защитить функции библиотеки от вызова.

0

Вы можете использовать компонент, который я создал для интеграции 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 в вашем приложении.

0

Вы можете использовать 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 и выполнять скрипты в этом контексте.

0

Вот как я смог добавить два внешних 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.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь