最近工作比较闲,所以学了点React和Redux相关的东西,然后又做了个简单的在线聊天室练手, 现在就记录下如何用React和Redux来构建一个简单的在线聊天室。
项目在线演示地址:https://murmuring-brook-22426.herokuapp.com/ (heroku可以用来免费部署一些自己的小项目玩,还是不错的。 缺点是国内的网访问有点慢。)
源码地址: Github (之后有时间也会陆续加点新功能、完善原有代码)
效果图:
后台server.js很简单:
/**
* Created by hshen on 9/23/16.
*/
// Import modules
var express = require('express');
var path = require('path');
var ejs = require('ejs');
// Create server
var app = express()
, server = require('http').createServer(app)
, io = require('socket.io').listen(server);
var port = process.env.PORT || 3000;
server.listen(port);
// Return index.html for '/'
app.get('/', function (req, res) {
res.render('index');
});
// Set path for views and static resources
app.set('views', './client/src/html');
app.set('view engine', 'html');
app.engine('html', ejs.renderFile);
app.use('/static', express.static('./client/build'));
var userNumber = 0;
io.sockets.on('connection', function (socket) {
var signedIn = false;
socket.on('newMessage', function (text) {
io.sockets.emit('newMessage',{
userName: socket.userName,
text: text
})
});
socket.on('signIn', function (userName) {
if (signedIn) return;
// we store the username in the socket session for this client
socket.userName = userName;
++userNumber;
signedIn = true;
io.sockets.emit('userJoined', {
userName: userName,
userNumber: userNumber
});
});
socket.on('disconnect', function () {
if (signedIn) {
--userNumber;
io.sockets.emit('userLeft', {
userName: socket.userName,
userNumber: userNumber
});
}
});
});
Chatting Room
用户在访问‘/’路径后,拿到的是如上的html,这里将会再去服务器请求打包后的index.js和common.js。
// js/pages/index.js , 项目入口文件
/**
* Created by hshen on 9/20/16.
*/
import $ from "jquery"
import React from 'react'
import { render } from 'react-dom'
import { createStore } from 'redux'
import { Provider } from 'react-redux'
import reducer from 'js/reducers'
import Routes from 'js/routes'
let store = createStore(reducer)
import 'css/main.less'
render(
{Routes}
,
$('.main')[0]
);
/**
* Created by hshen on 9/24/16.
*/
import React from 'react'
import ChatContainer from 'js/containers/ChatContainer';
import SignInContainer from 'js/containers/SignInContainer';
import { Router, Route, IndexRoute, browserHistory } from 'react-router';
const Routes = (
);
export default Routes;
/**
* Created by hshen on 9/24/16.
*/
import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import {bindActionCreators} from 'redux';
import Chat from 'js/components/chat/Chat';
import * as actions from 'js/actions/actions';
class ChatContainer extends Component {
render() {
return (
);
}
}
const mapStateToProps = (state, ownProps) => {
return {
messages: state.messages,
}
}
const mapDispatchToProps = (dispatch, ownProps) => {
return bindActionCreators({
receiveMessage: actions.receiveMessage,
sendMessage: actions.sendMessage,
userJoined: actions.userJoined,
userLeft: actions.userLeft
},dispatch);
}
export default connect(mapStateToProps, mapDispatchToProps)(ChatContainer)
/**
* Created by hshen on 9/24/16.
*/
import React, { Component, PropTypes } from 'react';
import MessageInput from 'js/components/chat/MessageInput';
import MessageItem from 'js/components/chat/MessageItem';
import Singleton from 'js/socket'
import 'css/chat.less'
export default class Chat extends Component {
constructor(props, context) {
super(props, context);
this.socket = Singleton.getInstance();
}
componentWillMount() {
const { receiveMessage, userJoined, userLeft } = this.props;
this.socket.on('newMessage',function (msg) {
receiveMessage(msg);
});
this.socket.on('userJoined',function (data) {
console.log(data);
userJoined(data);
});
this.socket.on('userLeft',function (data) {
console.log(data);
userLeft(data);
});
}
sendMessage(newMessage) {
const { sendMessage, userName } = this.props;
if (newMessage.length !== 0) {
sendMessage(newMessage);
this.socket.emit('newMessage', newMessage);
}
}
render() {
const { messages} = this.props;
return (
{messages.map( (message, index) =>
)}
);
}
}