はじめに
前回までに、Goを使って「2秒おきにメッセージを送り続けるサーバー」を作りました。
今回はStep 2として、そのデータをReact側で受け取って画面に表示させてみます。
「ライブラリは何を使うの?」と思うかもしれませんが、実はSSEはブラウザ標準の機能だけで実装できちゃいます。余計なインストールなしでサクッと作っていきましょう。
SSE実装の全体ロードマップ
- Step 1:Goで最小限のSSEサーバーを作る(完了!)
- 【本記事】Step 2:Reactでシグナルの受信を実装する
- Step 3:GoでHub(配信所)を設計し、一斉送信を可能にする
- Step 4:API送信と連携し、実用的なチャット基盤を完成させる
今回のゴール:最小構成の受信機を作る
動作デモ
画面のデザインは一切気にせず、「サーバーから届いた文字列をそのままリストに表示する」という最小構成のコンポーネントを作ります。
1. フロントエンドの準備
まずはViteを使ってReact(TypeScript)プロジェクトを立ち上げます。
(バックエンドのディレクトリの隣に作る想定です)
npm create vite@latest frontend -- --template react-ts
cd frontend
npm install
2. ReactでSSEを受け取る
src/App.tsx を以下のコードに書き換えます。
ブラウザ標準の EventSource というAPIを使うのが一番のポイントです。
import { useEffect, useState } from 'react'
function App() {
const [messages, setMessages] = useState<string[]>([])
useEffect(() => {
// 1. Step 1で作ったGoのサーバーにSSE接続を開始
const eventSource = new EventSource('http://localhost:8080/events')
// 2. サーバーからメッセージ(data)が届いた時の処理
eventSource.onmessage = (event) => {
console.log('New data:', event.data)
// 届いたデータを配列に追加
setMessages((prev) => [...prev, event.data])
}
// エラー(接続切れなど)が起きた時の処理
eventSource.onerror = (err) => {
console.error('SSE Error:', err)
}
// 3. クリーンアップ処理
// これを忘れると画面遷移のたびにコネクションが増えてしまうので注意!
return () => {
eventSource.close()
}
}, [])
return (
<div style={{ padding: '20px' }}>
<h1>SSE Receiver</h1>
<p>Goのサーバーから届いたデータが表示されます:</p>
<ul>
{messages.map((msg, i) => (
<li key={i}>{msg}</li>
))}
</ul>
</div>
)
}
export default App
実装のポイント
- useEffectで接続: コンポーネントが読み込まれたタイミングで接続を開始します。
-
自動再接続:
EventSourceは優秀で、もしネットワークが一時的に切れても、ブラウザが勝手に再接続を試みてくれます。自分でリトライ処理を書かなくていいのが最高ですね。 -
最後は必ずclose():
return () => eventSource.close()を書かないと、開発中のホットリロードなどで接続がどんどん増えてサーバーがパンクするので、ここは必須です。
3. 実際に動かしてみる
手順 1: バックエンドを起動
前回のディレクトリに移動して、Dockerを立ち上げておきます。
docker compose up
手順 2: フロントエンドを起動
別のターミナルでReactを起動します。
npm run dev
手順 3: ブラウザで確認
表示されたURL(http://localhost:5173 など)を開いてみてください。
2秒おきに {"time": "...", "message": "Ping!"} という文字列がポコポコ増えていけば大成功です!
おわりに
これで「サーバーから送られたものをReactで表示する」というパイプラインが繋がりました!
今は「全ユーザーに同じタイミングで2秒おきに送る」という一方的な仕組みですが、次回のStep 3では、Goの channel を使って「誰かが発言した時だけ、接続中の全員に通知を飛ばす」という、よりチャットに近い「配信所(Hub)」の仕組みを作っていきます!
