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>

두 방법 모두 원하는 스크립트를 실행하지 않는 것 같습니다. 나는 그것이 누락 된 간단한 것 같아요. 아무도 도와 줄 수 있습니까?

추신 : foobar를 무시하고 실제로 공유하고 싶지 않은 실제 ID가 있습니다.



답변

편집 : 상황이 빠르게 변하고 구식입니다-업데이트 참조


이 컴포넌트가 렌더링 될 때마다 또는이 컴포넌트가 DOM에 마운트 될 때마다 스크립트를 반복해서 페치하고 실행 하시겠습니까?

아마도 다음과 같이 시도하십시오.

componentDidMount () {
    const script = document.createElement("script");

    script.src = "https://use.typekit.net/foobar.js";
    script.async = true;

    document.body.appendChild(script);
}

그러나 이것은로드하려는 스크립트를 모듈 / 패키지로 사용할 수없는 경우에만 유용합니다. 먼저, 나는 항상 :

  • npm 에서 패키지를 찾으십시오.
  • 프로젝트에서 패키지를 다운로드하여 설치하십시오 ( npm install typekit).
  • import내가 필요한 패키지 ( import Typekit from 'typekit';)

이것은 패키지 reactreact-document-title예제 를 설치 한 방법 일 가능성이 있으며 npm에서 사용 가능한 Typekit 패키지가 있습니다 .


최신 정보:

이제 고리가 useEffect생겼으므로 다음과 같이 사용하는 것이 더 좋습니다 .

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);
  }
}, []);

다음은 커스텀 훅 (예 :)에 대한 훌륭한 후보입니다 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;

다음과 같이 사용할 수 있습니다.

import useScript from 'hooks/useScript';

const MyComponent = props => {
  useScript('https://use.typekit.net/foobar.js');

  // rest of your component
}


답변

위의 답변 외에도 다음을 수행 할 수 있습니다.

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)} />;
  }
}

div가 바인딩되고 this스크립트가 삽입됩니다.

데모는 codesandbox.io 에서 찾을 수 있습니다


답변

제가 가장 좋아하는 방법은 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>
    );
  }
};

https://github.com/nfl/react-helmet


답변

<script>SSR (서버 측 렌더링)에서 차단 이 필요한 경우 에는 접근 방식 componentDidMount이 작동하지 않습니다.

react-safe대신 라이브러리를 사용할 수 있습니다 . React의 코드는 다음과 같습니다.

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>


답변

Alex Mcmillan이 제공 한 답변 은 가장 도움이되었지만 더 복잡한 스크립트 태그에는 효과가 없었습니다.

나는 이미 “src”를 설정 한 다양한 기능을 가진 긴 태그에 대한 해결책을 제시하기 위해 그의 대답을 약간 조정했습니다.

(사용 사례의 경우 스크립트가 여기에 반영되어 머리 속에 살 필요가있었습니다) :

  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);
  }


답변

이 특정 사례에 대한 React 구성 요소를 만들었습니다 : https://github.com/coreyleelarson/react-typekit

Typekit Kit ID를 소품으로 전달하면됩니다.

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;


답변

를 사용하는 매우 좋은 해결 방법이 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));
}

이것은 임의의 HTML에서 작동하며 같은 컨텍스트 정보를 유지합니다 document.currentScript.