C++ ときどき ごはん、わりとてぃーぶれいく☆

USAGI.NETWORKのなかのひとのブログ。主にC++。

React プロジェクトの src 内のコンポーネントから諸事情によりウェブサイト外部の SCRIPT を読む方法のメモ

諸事情の例

4つの方法

もっとあるというのはさておき。

1. react-script-tag

この方法では DOM 構造的には in-situ な感じで <script> がぶちこまれます。

準備:

# .jsx 向けしか存在しないので .tsx では @ts-ignore して使います
yarn add react-script-tag

実用:

import React, { Component } from "react";
// note: ↓ .tsx ならこのコメントディレクティブを付けないとエラーになります。 .jsx なら不要です
// @ts-ignore
import ScriptTag from "react-script-tag";

export default class MyAwesomeMainCanvas extends Component {
  render() {
    return (
      <div>
        <canvas id="main-canvas"></canvas>
        <ScriptTag src="runner.main-canvas.something.js" />
      </div>
    );
  }
}

2. react-helmet

この方法では DOM 構造的には <head><script> (というか実際には任意の何かしら、 <title> とか <link> でも) をぶちこみます。

注意:

  • この方法を採用すると依存ライブラリーの都合か strict mode で警告↓がでて不穏になります。<script> 用途だけが目的の場合は他の方法がよいかもしれません。 ( Issue -> https://github.com/nfl/react-helmet/issues/426 )
index.js:1 Warning: Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code. See https://fb.me/react-unsafe-component-lifecycles for details.
* Move code with side effects to componentDidMount, and set initial state in the constructor.
Please update the following components: SideEffect(NullComponent)

準備:

# for .jsx
yarn add react-helmet
# for .tsx; 両方必要になります
yarn add react-helmet @types/react-helmet

実用:

import React, { Component } from "react";
// for .jsx & .tsx
import { Helmet } from "react-helmet";

export default class MyAwesomeMainCanvas extends Component {
  render() {
    return (
      <div>
        <canvas id="main-canvas"></canvas>
        <Helmet>
          <script src="runner.main-canvas.something.js"></script>
          <title>にゃーん/title>
        </Helmet>
      </div>
    );
  }
}

3. DOM 操作でぶちこむ

いわゆるごりごり手書きした的な方法。

import React, { Component } from "react";

export default class MyAwesomeMainCanvas extends Component {
  render() {
    return (
      <div>
        <canvas id="main-canvas"></canvas>
      </div>
    );
  }
  
  componentDidMount() {
    const s = document.createElement( "script" );
    s.src = "runner.main-canvas.something.js";
    s.async = true;
    document.body.appendChild( s );
  }
}

複数箇所で使用したいとか再利用性が欲しい場合は方法(1),(2)を選択するほかか、この方法(3)も手書きオレオレコンポーネント化する方法もあります。コンポーネント化の方法はこのメモの本論ではないので省略。

4. React の Effect Hook 機能

方法(3) のごりごり手書きを若干変態気味に実装する亜種のような方法です。

カスタム・フックを作って:

import { useEffect } from 'react';

export default const myHook =
  (src) =>
  {
    useEffect(
      () =>
      {
        const s = document.createElement( "script" );
        s.src = src;
        s.async = true;
        document.body.appendChild( s );
        return () => {
          document.body.removeChild( s );
        };
      }
    , [src]
    );
  };

カスタム・フックをひっかける:

// for .jsx
// import myHook from 'myHook.jsx';
// for .tsx
import myHook from 'myHook';

const Demo = props => {
  importScript("runner.main-canvas.something.js");
}

参考