はじめに
前回記事ではPostman経由でWebsocket通信の動作を確認してきました。
今回は、実際に画面上の操作でWebsocket通信の挙動を確認していきたいと思います。
サーバーサイドはNestJS、フロントエンドはReactの構成となります。
※サーバーサイドの実装は前回記事のソースを使用する前提で話を進めていきます。
前回記事
実装
サーバーサイド
まずは、サーバーサイドの実装になります。
といっても、前回記事で9割完成しており、あとは部分的な修正で完了です。
該当の修正箇所は2箇所です。
main.ts
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// await app.listen(3000); ←React側のポート番号と重複しないようにコメントアウト
await app.listen(9000); // ←追加
}
gateway.ts
// 修正前
@WebSocketGateway()
// 修正後
@WebSocketGateway({
cors: {
origin: ['http://localhost:3000'],
},
})
CORS許可の設定を追加しています。
フロントエンド
プロジェクト作成
npx create-react-app react-nest-websocket --template typescript
パッケージをインストール
npm add socket.io-client
実装
ソケット通信の設定部分を実装
src/contexts/WebsocketContext.tsx
import { createContext } from "react";
import { io, Socket } from "socket.io-client";
export const socket = io('http://localhost:9000');
export const WebsocketContext = createContext<Socket>(socket);
export const WebsocketProvider = WebsocketContext.Provider;
チャット画面の実装
src/components/Websocket.tsx
import { useContext, useEffect, useState } from "react"
import { WebsocketContext } from "../contexts/WebsocketContext"
type MessagePayload = {
content: string;
msg: string;
};
export const Websocket = () => {
const [value, setValue] = useState('');
const [messages, setMessages] = useState<MessagePayload[]>([]);
const socket = useContext(WebsocketContext);
useEffect(() => {
socket.on('onMessage', (newMessage: MessagePayload) => {
setMessages((prev) => [...prev, newMessage]);
});
return () => {
socket.off('connect');
socket.off('onMessage');
}
}, );
const onSubmit = () => {
socket.emit('newMessage', value);
setValue('');
}
return (
<div>
<div>
<h1>チャットアプリ</h1>
<div>
{messages.length === 0 ? <div>まだメッセージがありません。</div> : <div>
{messages.map((msg, idx) => <div key={idx}>
<p>{msg.content}</p>
</div>)}</div>}
</div>
<div>
<input
type="text"
value={value}
onChange={(e) => setValue(e.target.value)}
/>
<button onClick={onSubmit}>Submit</button>
</div>
</div>
</div>
)
}
上記追加したファイルをインポートと登録
src/App.tsx
import './App.css';
import { Websocket } from './components/Websocket';
import { socket, WebsocketProvider } from './contexts/WebsocketContext';
function App() {
return (
<WebsocketProvider value={socket}>
<Websocket />
</WebsocketProvider>
);
}
export default App;