Reactを中心にフロントエンド開発をはじめ既に6年以上たちます。その間に入門書作りながら学ぶ React入門(もう内容が古いので購入しないで下さいね)を書いたり、React教育コース(こちらは最新のReactに対応しています!)も行っていますが、またにWebブラウザーの知らないAPIを発見して驚きます。
現在、開発しているアプリでは複数のTAB(またはウィンドウ)で開いている同一アプリの間で情報交換する必要が出てきました。
別TABアプリとのコミュニケーション方法
ざっと調べたところブラウザーの持つAPIでできそうなものは、以下があります(もちろんサーバーを関連させれば他の方法もあるとおもいます)。
- sessionStorage sessionStorage(localStorage)が変更されると、storage イベントが発生するので情報交換に使えます
- postMessage Windowオブジェクトに結び付いた通信機能です、異なるオリジン(サーバー、ポート番号)から読み込まれたアプリ間でも通信できます
- Channel Messaging ペアリングを行った2つのアプリ専用の通信チャンネルを作れます
- Broadcast Channel 名前の付いたチェネルに対してブロードキャスト情報を送信できます
このようなコミュニケーション系のAPIは今回調べて初めて知りました。😅
今回のアプリでの利用は双方向の通信や複雑なやり取りは行わないので、簡単に使え、他のアプリと干渉しにくいBroadcast Channelが1番かなと思います。次点はsessionStorage、Channel Messaging でしょうか?
Broadcast Channel
Broadcast Channelの動作を確認するために、簡単なアプリを作ってみました。
まずは、このアプリを2つのウィンドウで動かした画面をご覧ください。
コード
当然Reactを使ったコードです。
- ① 受信したメッセージ表示用ステート
- ② BroadcastChannelを作成
- チャンネル名は
test-message
、この名前は他アプリと重ならないような名前にしないといけませんね - BroadcastChannelオブジェクトをReactの再表示毎に作成しないように、メモ化してチャネルを再利用しています
- チャンネル名は
- ③
onmessage
イベントで受信メッセージを取得できます - ④ 送信は
postMessage()
メソッドでできます
import { useMemo, useState } from 'react';
const App = () => {
const [message, setMessage] = useState(""); // ← ①
const channel = useMemo(() => new BroadcastChannel('test-message'), []); // ← ②
channel.onmessage = (e) => setMessage(e.data); // ← ③
const post = (s: string) => channel.postMessage(s); // ← ④
return (
<>
<button onClick={() => post("button A")}> A </button>
<button onClick={() => post("button B")}> B </button>
<p>{message}</p>
</>
);
}
export default App;
まとめ
Broadcast Channelを使うと複数TAB(複数ウィンドウ)で動くアプリ間の情報交換できることがわかりました。通常のReact等で作られたSPAが複数TABで動作する事はあまりないかもしれませんが、もし何らかの理由で複数TAB起動があり連携する場合は、簡単に使えるBroadcast Channelを検討してみると良いかと思います。