⛅
Reactでインスタグラム投稿の埋め込みを行った時にハマったこと
概要
あけましておめでとうございます、みなさん新年いかがお過ごしでしょうか。
私は新年早々、インスタグラム投稿の埋め込みとたたかっていました。。新年一発目はそこでハマった内容を書いてみます。
やりたいこと
- インスタグラムの埋め込みコードをDBに保存します。インスタの埋め込みコードについてはインスタグラムをブログやウェブサイトへ埋め込む方法と埋め込みインスタ活用術を参考のこと。
- DBから自作のAPI経由で、この埋め込みコードを取得します。
- 埋め込みコードを
dangerouslySetInnerHTML
に埋め込みます。なお、dangerouslySetInnerHTMLの詳細についてはReactのdangerouslySetInnerHTML使ってみたを参照のこと。
課題と原因
- 埋め込んだコードの投稿が表示されず、下記のような結果になりました。
- 原因は、埋め込んだコードに含まれているscriptタグ
//www.instagram.com/embed.js
が実行されていないことです。これをどうにかして実行させる必要があります。
対応
- 全ての投稿の埋め込みコードのHTML描画が終わった段階で、embed.jsを読みこむ必要があります。つまりreactのDOM構築後に、js読み込みをおこないます。
- インスタの埋め込みコードに含まれている、embed.jsのscriptタグは削除します。
- タイミングとしては
componentDidMount
のタイミングになります。componentDidMountの処理タイミングについてはreactのDOM構築後に特定の処理を行いたいの記事が参考になります。今回はuseEffectでcomponentDidMountを代用するを参考に、useEffectで実装します。 - useEffect内の処理ではReactでscriptタグを生成しスクリプトを実行/外部スクリプトを読み込む方法を参考に、embed.jsを読みこませる処理を実行します。
実装サンプル
export default function InstagramReactSample() {
const [posts, setPosts] = useState([]);
useEffect(() => {
// 自作で用意したバックエンドからインスタグラムの埋め込みコードを取得しセット(詳細は割愛)
getPosts(setPosts);
}, []);
useEffect(() => {
// 投稿の描画が終わったらスクリプトを読みこませる。
if (posts.length > 0) {
const script = document.createElement("script");
script.type = "text/javascript";
var attr = document.createAttribute("src");
attr.value = "//www.instagram.com/embed.js";
script.setAttributeNode(attr);
const head = document.getElementsByTagName("head")[0];
head.appendChild(script);
}
}, [posts]);
return (
{/* インスタグラムの埋め込みコード */}
<div>
{posts.length > 0 && (
<>
{posts.map((p) => {
return (
<div dangerouslySetInnerHTML={{ __html: p.instagramCode }} />
);
})}
</>
)}
</div>
);
}
Discussion
有益な情報をありがとうございます。
※ 以下参考になるかも分からないちょっとした情報なのでスルーしていただければと思います。
最近Twitterの埋め込みで同じような問題(scriptタグをそのまま突っ込んでも表示されない)と戦いまして、最終的にはWebComponentsを使って対応しました。IEは非対応ですが…。
参考:Web Componentsを利用したZennマークダウン部分の改善について
書いていただいているように
useEffect
でscriptを読み込むのが基本的には楽でベストプラクティスだと思うのですが、初期化しないといけない部分が増えてきたときにはWeb Componentsを使うと1回で済ませられて楽だったりします。おぉ、ありがとうございます。
Web Components全然知らなかった。。すごい参考になります。