0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

NestJS+Reactで簡易チャットアプリを作ってみる

Posted at

はじめに

前回記事では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;

完成

利用者Aさんの画面(既にメッセージ入力済み)
スクリーンショット 2023-02-13 17.19.17.png

利用者Bさんの画面(未入力の状態)
スクリーンショット 2023-02-13 17.19.25.png

このあと利用者Bさんが「はじめまして〜利用者Bです」と入力した時のAさんとBさんの画面結果
利用者Aさん
スクリーンショット 2023-02-13 17.22.11.png

利用者Bさん
スクリーンショット 2023-02-13 17.22.18.png

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?