ReactのuseEffectでWebSocketを利用する方法を初心者向けに解説
生徒
「先生、Reactでリアルタイムにデータを受け取りたいんですが、どうすればいいんですか?」
先生
「その場合はWebSocketという仕組みを使うと便利です。サーバーとブラウザが常につながっていて、すぐに情報をやりとりできます。」
生徒
「普通の通信と何が違うんですか?」
先生
「普通のHTTP通信は『必要なときに取りに行く』ですが、WebSocketは『ずっと電話をつないでいる』ようなものです。ReactではuseEffectを使ってWebSocketを安全に扱います。」
1. WebSocketとは?初心者でもわかるリアルタイム通信
WebSocketとは、サーバーとブラウザが常に接続された状態で、双方向にデータをやりとりできる仕組みです。例えばチャットアプリで相手のメッセージがすぐに画面に表示されるのは、このWebSocketを利用している場合が多いです。
たとえるなら、手紙を送るのがHTTP通信、電話で会話するのがWebSocket通信です。手紙は届くまで時間がかかりますが、電話なら相手がしゃべった瞬間に声が届きます。
2. useEffectでWebSocketを使う基本
ReactのuseEffectは、コンポーネントが表示されたときに処理を実行し、画面を閉じたときに後片付けをするのに便利です。WebSocketは接続と切断の処理が必要なので、useEffectと組み合わせるのがベストプラクティスです。
import React, { useEffect, useState } from "react";
function App() {
const [message, setMessage] = useState("接続待ち...");
useEffect(() => {
const socket = new WebSocket("wss://echo.websocket.org");
socket.onopen = () => {
setMessage("WebSocketに接続しました");
socket.send("こんにちはサーバー!");
};
socket.onmessage = (event) => {
setMessage("サーバーから: " + event.data);
};
return () => {
socket.close();
};
}, []);
return <h1>{message}</h1>;
}
export default App;
3. クリーンアップ処理の重要性
WebSocketは接続しっぱなしになるので、不要になったら必ず切断する必要があります。切断せずに放置すると、無駄にサーバーとの通信が続き、パソコンやスマホに負担がかかります。
useEffectでは、return () => socket.close()を忘れずに書くのが基本です。これが「クリーンアップ処理」です。掃除や片付けと同じで、最後にきちんと後始末をしておくとアプリが安定します。
4. 実際のアプリでの利用例
WebSocketは次のようなアプリでよく使われます。
- チャットアプリ(相手のメッセージを即時に表示)
- 株価や暗号資産のリアルタイム表示
- オンラインゲームのプレイヤー位置情報の共有
- 通知システム(新しいお知らせを瞬時に反映)
これらのアプリは「今すぐにデータを更新したい」ので、WebSocketとReactのuseEffectの組み合わせがとても役立ちます。
5. 初心者が気をつけるポイント
WebSocketを扱うときに初心者が混乱しやすいのは、接続が二重になってしまうことです。特にReactの開発モード(StrictMode)ではuseEffectが二度動くことがあるので、接続が二重になるケースがあります。
対策としては、クリーンアップ処理を必ず書くことと、必要なら「すでに接続していないか」をチェックしてから新しく接続する工夫をすると安心です。
また、サーバーが落ちた場合や通信が切れた場合のエラー処理も忘れずに実装しておくと、より実用的なアプリになります。
まとめ
ここまで、ReactのuseEffectフックを利用してWebSocket通信を実装する基本的な方法から、クリーンアップ処理の重要性、そして実戦で役立つ注意点まで詳しく解説してきました。現代のWebアプリケーションにおいて、ユーザー体験を飛躍的に向上させる「リアルタイム性」は欠かせない要素です。チャットアプリ、通知システム、金融データのダッシュボードなど、WebSocketが活躍する場面は多岐にわたります。
ReactでのWebSocket運用の要点
ReactでWebSocketを扱う際の最も重要なポイントは、「コンポーネントのライフサイクルと通信の同期」です。useEffectの依存配列を空[]に設定することで、マウント時に一度だけ接続を確立し、アンマウント時にクリーンアップ関数で確実に切断する。この一連の流れを守るだけで、メモリリークや接続の多重増殖といった、初心者によくあるトラブルの大部分を回避できます。
また、実際の開発現場では、素のWebSocket APIだけでなく、再接続処理やルーム管理を容易にする「Socket.io」などのライブラリを併用することも一般的です。しかし、まずは今回学習した標準のWebSocketオブジェクトの使い方をマスターすることで、通信の仕組み自体を深く理解でき、どんなライブラリにも応用できる基礎体力が身につきます。
応用:複数のメッセージをリスト表示する実装例
学んだことを活かして、受信したメッセージを次々とリストに追加していく、より実践に近いコードを確認してみましょう。
import React, { useEffect, useState } from "react";
function ChatApp() {
const [messages, setMessages] = useState([]);
const [input, setInput] = useState("");
const [ws, setWs] = useState(null);
useEffect(() => {
// WebSocketサーバーへの接続
const socket = new WebSocket("wss://echo.websocket.org");
socket.onopen = () => {
console.log("サーバーに接続しました");
};
socket.onmessage = (event) => {
// サーバーからの返信をリストに追加
setMessages((prev) => [...prev, event.data]);
};
socket.onclose = () => {
console.log("サーバーから切断されました");
};
setWs(socket);
// クリーンアップ処理
return () => {
socket.close();
};
}, []);
const sendMessage = () => {
if (ws && input) {
ws.send(input);
setInput("");
}
};
return (
<div style={{ padding: "20px" }}>
<h3>リアルタイムチャット体験</h3>
<input
type="text"
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder="メッセージを入力"
/>
<button onClick={sendMessage}>送信</button>
<ul style={{ marginTop: "20px" }}>
{messages.map((msg, index) => (
<li key={index}>{msg}</li>
))}
</ul>
</div>
);
}
export default ChatApp;
上記のコードでは、useStateでメッセージの配列を管理し、サーバーからデータが届くたびにスプレッド構文を使って新しい配列を作成・更新しています。このように、Reactの「状態(State)」とWebSocketを組み合わせることで、動的でインタラクティブなUIが簡単に構築できるのです。
最後に:さらなるステップアップに向けて
WebSocketの実装に慣れてきたら、次は「カスタムフック」化に挑戦してみるのがおすすめです。useWebSocketのような独自フックを作成すれば、複数のコンポーネントで同じロジックを使い回すことができ、コードの可読性と保守性が格段に向上します。
ネットワーク通信は目に見えない部分が多いため、最初は難しく感じるかもしれません。しかし、ブラウザのデベロッパーツールの「Network」タブを覗いて、実際にデータが流れている様子を確認しながら進めれば、必ず理解は深まります。今回の記事が、あなたのReact開発におけるリアルタイム通信実装の第一歩になれば幸いです。
生徒
「先生、ありがとうございました!useEffectの中でsocket.close()を書く理由がやっと分かりました。これを忘れると、ページを移動するたびに新しい接続が作られちゃって、ブラウザが重くなる原因になるんですね。」
先生
「その通りです!よく気づきましたね。Webアプリは『見えないところで動いているもの』をいかに制御するかが大切です。特にWebSocketのような持続的な接続は、お片付けが命ですよ。」
生徒
「さっきのコード例で、メッセージがリストになって表示されるのがすごく面白かったです。これを使えば、SNSのリアルタイム通知や、共同編集ツールみたいなものも作れそうな気がしてきました!」
先生
「いい意気込みですね。実はモダンなWebアプリの多くは、裏側でこうした非同期通信を駆使しています。次はエラーハンドリング、例えば『もしインターネットが途切れたらどう再接続するか』といった課題にも挑戦してみてください。よりプロフェッショナルなエンジニアに近づけますよ。」
生徒
「はい!まずはデベロッパーツールで通信の中身を観察しながら、もっと色々なデータを送受信して遊んでみます!」
先生
「その好奇心が一番の上達の近道です。頑張ってくださいね!」