チャットサービスを作ってみる

websocketの勉強のため、チャットサービスを作ってみます。
開発環境は他記事で記載している「React+Node+Docker+Postgres」です。

websocket

websocketを実行するために下記をインストールします。

npm install -S socket.io socket.io-client

バックエンド

socket.ioを利用します。
websocketで受信したときDBに登録します。
DBから値を取得するAPIも用意しておきます。

./src/app/js/main.js

const express = require("express");
const path = require("path");
const db = require('./models/index')
const socket = require('socket.io');

const app = express();

app.get('/api/chat', (req, res) => {
 db.chat.findAll().then(records => {
   res.send(records);
 });
})

const server = app.listen(3000, () => {
 console.log('app running');
});

const io = socket(server);

io.on('connection', (socket) => {
 console.log("socketid: " + socket.id);

 socket.on('SEND_MESSAGE', function (data) {
   console.log('data:' + data);
   db.chat.create(data);
   io.emit('RECEIVE_MESSAGE', data);
 })
});

DBのモデルも作成します。

./src/app/js/models/chat.js

'use strict';
const {
 Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
 class chat extends Model {
   /**
    * Helper method for defining associations.
    * This method is not a part of Sequelize lifecycle.
    * The `models/index` file will call this method automatically.
    */
   static associate(models) {
     // define association here
   }
 };
 chat.init({
   username: DataTypes.STRING,
   comment: DataTypes.STRING
 }, {
   sequelize,
   modelName: 'chat',
   freezeTableName: true
 });
 return chat;
};


フロントエンド

socket.io-clientを利用します。
websocket受信時にコメントを追加表示します。
画面の初期表示時にはDBからコメントを取得して表示しています。

./src/front/js/chat/Chat.jsx

import React, { Component } from 'react';
import { getJSON } from "../utils/HttpUtils";
import io from "socket.io-client";

export default class ChatApp extends React.Component {
   constructor(props) {
       super(props);

       this.state = {
           username: '',
           comment: '',
           comments: []
       };

       this.socket = io('0.0.0.0:3000');

       this.socket.on('RECEIVE_MESSAGE', function (data) {
           addComment(data);
       });

       const addComment = data => {
           this.setState({ comments: [...this.state.comments, data] });
           console.log(this.state.comments);
       };

       this.sendComment = event => {
           event.preventDefault();
           this.socket.emit('SEND_MESSAGE', {
               username: this.state.username,
               comment: this.state.comment
           })
           this.setState({ comment: '' });

       }
   }

   componentDidMount() {
       getJSON("/api/chat")
           .then(chatResponseJson => this.setState({ comments: chatResponseJson }));
   }

   render() {
       return (
           <div className="container">
               <div className="body">
                   <div className="title">Chat</div>
                   <hr />
                   <div className="comments">
                       {this.state.comments.map(comment => {
                           return (
                               <div>{comment.username}: {comment.comment}</div>
                           )
                       })}
                   </div>

               </div>
               <div className="footer">
                   <input type="text" placeholder="Username" value={this.state.username} onChange={ev => this.setState({ username: ev.target.value })} />
                   <br />
                   <input type="text" placeholder="Comment" value={this.state.comment} onChange={ev => this.setState({ comment: ev.target.value })} />
                   <br />
                   <button onClick={this.sendComment}>コメントする</button>
               </div>
           </div>
       );
   }
}

./src/front/js/main.js

import React from "react";
import ReactDOM from "react-dom";
import ChatApp from './chat/Chat';

const Index = () => {
 return (
   <div><ChatApp /></div>
 );
};

ReactDOM.render(<Index />, document.getElementById("root"));

DB

Postgres起動時にテーブル作成とテストデータ投入用のsqlを作成します。

./db/init/1_createtable.sql

create table if not exists chat(
id       SERIAL PRIMARY KEY,
username         VARCHAR(20),
comment   VARCHAR(100),
"createdAt"   TIMESTAMP NOT NULL,
"updatedAt"   TIMESTAMP NOT NULL
);

./db/init/2_insert-chat.sql

INSERT INTO chat (username, comment, "createdAt", "updatedAt") VALUES ('ichiro', 'Hello Chat', now(), now());

起動

docker-compose build --no-cache
docker-compose up

画像1

こちらのソースは下記になります。
https://github.com/YosukeKondo/react-node-docker-postgres/tree/chat

この記事が気に入ったらサポートをしてみませんか?