トラブル
原因の特定方法
よくある原因としては「ブラウザのページのロードが完了してない時にwebsocketの接続をしようとしている」というものである.
これが原因かどうかは次の手順を踏んで確認してください.
解決策
vanillaのjavascriptで書いてる場合は,次のように
ページロード時に起動する関数を
EventListener
で設定すればOKjavascriptの設定
var webSocket; // ウェブソケット
window.addEventListener('load', connect); // ページロード時にconnectを起動するように設定
// サーバとの通信を接続する関数
function connect(){
webSocket = new WebSocket("ws://localhost:8000/");
webSocket.onmessage = (message) => {
console.log(message.data);
};
}
function sendMessage(){
// ...
}
解決策(Next.jsの場合)
どうやら開発者モードで作業する際,reactStrictMode
をtrue
にしていると,useEffectが2回呼び出されるらしい(参考).
1回目の呼び出しの際はwebsocketを一瞬繋いですぐに接続を切るためか,エラーが発生してしまう.
解決策としては次の2つが考えられる.
- (正しい対応)「next.config.js」に書かれている
reactStrictMode
をfalse
にする - (応急処置)下のソースコードのように,useEffectのreturn文をコメントアウトする
export default function Home() {
const [ws, setWs] = useState(null);
// 起動時にwebsocketを接続するuseEffect
useEffect(() => {
const socket = new WebSocket(url);
socket.onmessage = (event) => {
console.log(event.data);
};
// useEffectではコンポーネントのアンマウント時に起動する関数をreturnする
// !!! ここでのトラブルを解決するために,接続解除する関数のreturnをコメントアウト !!!
// return () => {
// socket.close()
// };
}, []);
return <div>WebSocket Test Page</div>;
}
おわりに
- アプリケーション作るときに毎回同じ失敗してるので覚書として残します.
- 他の誰かも同じ問題を抱えているはず...
- 修正前の問題があるソースコードでも環境を変えるとうまく接続できたりするので,ぶっちゃけよくわかってないところがある.