チャットサービスを作ってみる
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
こちらのソースは下記になります。
https://github.com/YosukeKondo/react-node-docker-postgres/tree/chat
この記事が気に入ったらサポートをしてみませんか?