ReactJs - Xây dựng ứng dụng chat và deploy lên web - Phần 2
Bài đăng này đã không được cập nhật trong 3 năm
Ở phần trước mình đã xây dựng demo được một ứng dụng chat cơ bản, các bạn có thể xem lại tại đây https://viblo.asia/p/reactjs-xay-dung-ung-dung-chat-va-deploy-len-web-phan-1-Az45bAvwlxY Phần này sẽ làm thêm 1 chức năng định danh người chat và hiển thị những ai đang online và deploy ứng dụng lên heroku
Xây dựng phòng chat
Về phía client react
trong các bạn mở file src/App.js
thay đổi nội dung thành như này, mình sẽ comment giải thích trực tiếp trong code cho các bạn dễ hiểu
import React from 'react';
import $ from 'jquery';
import Messages from './message-list';
import Input from './input';
import _map from 'lodash/map';
import io from 'socket.io-client';
import './App.css';
export default class App extends React.Component {
constructor(props) {
super(props);
//Khởi tạo state,
this.state = {
messages: [], // danh sách tin nhắn
user: {id: '', name: ''},// người dùng hiện tại, nếu rỗng sẽ hiển thị form login, có sẽ hiển thị phòng chat
userOnline:[] // danh sách người dùng đang online
}
this.socket = null;
}
//Connetct với server nodejs, thông qua socket.io
componentWillMount() {
console.log(this.state.user)
this.socket = io('localhost:6969');
this.socket.on('newMessage', (response) => {this.newMessage(response)}); //lắng nghe khi có tin nhắn mới
this.socket.on('loginFail', (response) => {alert('Tên đã có người sử dụng')}); //login fail
this.socket.on('loginSuccess', (response) => {this.setState({user: {id: this.socket.id, name: response}})}); //đăng nhập thành công
this.socket.on('updateUesrList', (response) => {this.setState({userOnline: response})}); //update lại danh sách người dùng online khi có người đăng nhập hoặc đăng xuất
}
//Khi có tin nhắn mới, sẽ push tin nhắn vào state mesgages, và nó sẽ được render ra màn hình
newMessage(m) {
const messages = this.state.messages;
let ids = _map(messages, 'id');
let max = Math.max(...ids);
messages.push({
id: max+1,
userId: m.user.id,
message: m.data,
userName: m.user.name
});
let objMessage = $('.messages');
if (objMessage[0].scrollHeight - objMessage[0].scrollTop === objMessage[0].clientHeight ) {
this.setState({messages});
objMessage.animate({ scrollTop: objMessage.prop('scrollHeight') }, 300); //tạo hiệu ứng cuộn khi có tin nhắn mới
} else {
this.setState({messages});
if (m.id === this.state.user) {
objMessage.animate({ scrollTop: objMessage.prop('scrollHeight') }, 300);
}
}
}
//Gửi event socket newMessage với dữ liệu là nội dung tin nhắn và người gửi
sendnewMessage(m) {
if (m.value) {
this.socket.emit("newMessage", {data:m.value, user: this.state.user}); //gửi event về server
m.value = "";
}
}
//login để định danh người dùng
login() {
this.socket.emit("login", this.refs.name.value);
}
render () {
return (
<div className="app__content">
<h1>chat box</h1>
{/* kiểm tra xem user đã tồn tại hay chưa, nếu tồn tại thì render form chat, chưa thì render form login */}
{ this.state.user.id && this.state.user.name ?
<div className="chat_window">
{/* danh sách user online */}
<div className="menu">
<ul className="user">
<span className="user-name">{this.state.user.name}</span>
<p>Online</p>
{this.state.userOnline.map(item =>
<li key={item.id}><span>{item.name}</span></li>
)}
</ul>
</div>
{/* danh sách message */}
<div className="content">
<Messages user={this.state.user} messages={this.state.messages} typing={this.state.typing}/>
<Input sendMessage={this.sendnewMessage.bind(this)}/>
</div>
</div>
:
<div className="login_form">{/* form login */}
<input type="text" name="name" ref="name"></input>
<input type="button" name="" value="Login" onClick={this.login.bind(this)}></input>
</div>
}
</div>
)
}
}
Message cần hiển thị cả tên người gửi nên sẽ thay đổi 1 chút src/mesage-item.js
import React from 'react';
export default class messageItem extends React.Component {
render () {
return (
<li className={this.props.user? "message right appeared": "message left appeared"}>
<div className="avatar"></div>
<div className="text_wrapper">
<div className="text"><b>{this.props.message.userName}</b><br></br>{this.props.message.message}</div>
</div>
</li>
)
}
}
Về phía server node js
mở file index.js
và thay đổi nội dung như sau
var express = require('express');
var app = express();
var _findIndex = require('lodash/findIndex') // npm install lodash --save
var server = require('http').Server(app);
var port = (process.env.OPENSHIFT_NODEJS_PORT || process.env.PORT || 6969);
var io = require('socket.io')(server);
server.listen(port, () => console.log('Server running in port ' + port));
var userOnline = []; //danh sách user dang online
io.on('connection', function(socket) {
console.log(socket.id + ': connected');
//lắng nghe khi người dùng thoát
socket.on('disconnect', function() {
console.log(socket.id + ': disconnected')
$index = _findIndex(userOnline, ['id', socket.id]);
userOnline.splice($index, 1);
io.sockets.emit('updateUesrList', userOnline);
})
//lắng nghe khi có người gửi tin nhắn
socket.on('newMessage', data => {
//gửi lại tin nhắn cho tất cả các user dang online
io.sockets.emit('newMessage', {
data: data.data,
user: data.user
});
})
//lắng nghe khi có người login
socket.on('login', data => {
// kiểm tra xem tên đã tồn tại hay chưa
if (userOnline.indexOf(data) >= 0) {
socket.emit('loginFail'); //nếu tồn tại rồi thì gửi socket fail
} else {
// nếu chưa tồn tại thì gửi socket login thành công
socket.emit('loginSuccess', data);
userOnline.push({
id: socket.id,
name: data
})
io.sockets.emit('updateUesrList', userOnline);// gửi danh sách user dang online
}
})
});
app.get('/', (req, res) => {![](https://images.viblo.asia/388d121e-72d0-4fc0-b946-bd4f3e125f94.png)
res.send("Home page. Server running okay.");
})
Deploy lên web
Để có thể deploy ứng dụng, bạn cần có 1 tài khoản github và 1 tài khoản heroku nhé
Deploy server chat
Các bạn thêm file Procfile
vào thư mục gốc của project với nội dung web: node index.js
, đây là file cấu hình cho heroku biết nó sẽ phải chạy project của bạn thế nào
Tiếp theo các bạn vào trang heroku tạo 1 ứng dụng mới
chọn new->create new app, sau đó điền tên ứng dụng của bạn tù thích, điền tên xong thì Create app
Tạo xong các bạn được chuển hướng đến màn hình quan lý của ứng dụng, kéo xuống chọn liên kết với github
Kéo xuống dưới chọn deploy branch mà bạn vừa push lên github, đợi quá trình deploy xong, các bạn lên đầu trang và click vào Opend app, các bạn được chuyển hướng đến trang với dòng chữ Home page. Server running okay.
là đã deploy đươc server chat thành công
Các bạn nhớ chú ý tên miền của ứng dụng, ta sẽ dùng nó vào việc kết nối từ client chát với server chat
Deploy client chat
Về bản chất client chat chỉ là 1 trang tĩnh nên ta sẽ dùng tính năng GitHub Pages của github
Các bạn đăng nhập vào github, tạo 1 repository tên gì cũng được, mình đặt là client-chat
trong file /src/App.js
, phần khởi tạo kết nối socket, ta không sử sủng địa chỉ localhost:6969
nữa mà dùng địa chỉ của server node js mà chúng ta vừa deploy ở trên, địa chỉ của mình là https://chattaap.herokuapp.com/
this.socket = io('https://chattaap.herokuapp.com/');
Sau khi tạo repository rồi thì push code từ local lên thôi, nhưng trước khi push, các bạn kiểm tra file package.json
, trường homepage
các bạn hay thay tên repository và tên tài khoản git của bạn vào
{
"name": "client",
"version": "0.1.0",
"private": true,
"homepage": "https://ththth0303.github.io/chat-client",
"author": "Thang",
"dependencies": {
"an-array-of-english-words": "^1.3.1",
"gh-pages": "^1.0.0",
"jquery": "^3.2.1",
"lodash": "^4.17.4",
"react": "^16.0.0",
"react-dom": "^16.0.0",
"react-scripts": "1.0.14",
"socket.io-client": "^2.0.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject",
"deploy": "react-scripts build && gh-pages -d build"
}
}
Tiếp theo là push lên remote reposirory, push xong các bạn chạy lệng npm run deploy
, đợi khi hoàn thành
Giờ các bạn có thể vào trang https://{tài khoản git}/github.io/{repository}, của mình là https://ththth0303.github.io/chat-client/
Các bạn nhập tên và click login xem có vào phòng chat được không nhé
Như này là bạn đã thành công
Kết
Việc deploy lên web cũng k quá phức tạp, phần tiếp theo chúng ta sẽ lưu database người dùng, tin nhắn và một chức năng nhỏ nữa là typing(hiển thi ai đang nhập tin nhắn) Chat client https://github.com/ththth0303/chat-client/tree/part2 Chat server https://github.com/ththth0303/chat-server Demo https://ththth0303.github.io/chat-client/
All rights reserved