HOWTO · React

React アプリケーションで Iframe を表示する

この記事では、React アプリケーション内で iframe を表示するための 2つの異なるアプローチについて説明します。

このページの内容

Reactでiframeを表示するには、URLやサイズをデータとして扱える場合、属性を明示した<iframe>要素を使います。dangerouslySetInnerHTMLを使うのは、入力がすでにHTML文字列であり、それをマークアップとして挿入する必要がある場合に限ります。

Reactコンポーネントで構造化データからiframeを表示する

iframeのURL、タイトル、幅、高さをそれぞれ別の値として扱える場合は、関数コンポーネントにpropsとして渡します。こうするとiframeの属性がコンポーネント内で明確になり、HTML文字列を解析する必要もありません。たとえば、コンポーネントはfunction IframeEmbed({ src, title, width = 640, height = 360 }) { return <iframe src={src} title={title} width={width} height={height} />; }のように定義できます。<IframeEmbed src="https://example.com/embed" title="Example content" />のように値を渡して表示します。

これらの値に対応するブラウザーのマークアップを次に示します。表示例のタイトルは英語の「Example content」のままです。

<iframe src="https://example.com/embed" title="Example content" width="640" height="360"></iframe>

Reactコンポーネントでは、上の例のように値を直接渡します。支援技術を使う人が内容を把握できるよう、iframeには適切なtitleを指定してください。サーバーから個別のフィールドではなく文字列が送られてくる場合は、その形式が必要なときに限り、下のHTML文字列の方法を使います。構造化データとして取得できる値を取り出すためだけに、マークアップを解析する必要はありません。

このJavaScript例は構造化データの形を示し、タイトルとサイズを出力します。この例はこのローカライズでは実行確認されていません。同じ値をコンポーネントに渡すには、<IframeEmbed {...iframe} />をレンダーします。スプレッド構文によってsrc、title、width、heightがpropsとして渡されます。

const iframe = {
  src: "https://example.com/embed",
  title: "Example content",
  width: 640,
  height: 360
};

console.log(`${iframe.title}: ${iframe.width}×${iframe.height}`);

dangerouslySetInnerHTMLでHTML文字列からiframeを埋め込む

APIによっては、iframeタグ全体を文字列で返すことがあります。Reactでは、値として__htmlキーを持つオブジェクトを受け取るdangerouslySetInnerHTML propを使って、そのマークアップを挿入できます。たとえば、const iframeSource = '<iframe src="https://example.com/embed" title="Example content" width="640" height="360"></iframe>';を設定し、<div dangerouslySetInnerHTML={{ __html: iframeSource }} />をレンダーします。

この方法が受け取るのはHTMLマークアップであり、iframeのプロパティをまとめたオブジェクトではありません。この文字列は信頼できるHTMLとして扱ってください。攻撃者が制御する内容をdangerouslySetInnerHTMLでレンダーすると、クロスサイトスクリプティング(XSS)につながる可能性があります。レンダーする前に、適切な信頼境界でデータを検証またはサニタイズしてください。新しい連携では、可能であればサーバーにiframeの値を構造化データとして返すよう依頼し、通常の<iframe>要素を使いましょう。

iframeのセキュリティと読み込みに関するトレードオフを理解する

Reactアプリケーションでiframeを使うこと自体が危険なわけではありません。ブラウザーの同一オリジンポリシーにより、異なるオリジンから埋め込まれたページが親ページのドキュメントを読み取ったり変更したりすることは制限されます。一方、postMessageなどの仕組みを通じてページ間で通信することはできます。同一オリジンの埋め込みページは、制限がなければ親ページとやり取りできる場合があります。埋め込み元のページにも注意し、信頼できる遷移先を選んでください。埋め込み内容に適した制限を設定できる場合は、iframeのsandbox属性を使います。sandboxはスクリプトやナビゲーションを制限できますが、必要な権限トークンだけを指定してください。組み合わせによっては分離が弱まることがあります。

埋め込んだページの読み込みには時間やリソースがかかり、ページ全体の使い勝手に影響する場合があります。影響の大きさは埋め込み先、端末、iframeの読み込み方によって異なり、必ず性能が低下するわけではありません。用途に合い、環境が対応している場合は、loading="lazy"属性で画面外にあるiframeの読み込みを遅らせられます。レイアウトのずれを抑えるため適切なサイズを指定し、アプリケーションのセキュリティポリシーに照らして埋め込みページの動作を確認してください。