Nodejs and SocketIO Giuseppe Attardi Code https githubcom attardi ReactJS Realtime Chat http danialkgithubio blog20130616 reactjs andsocketdot ID: 639288
Download Presentation The PPT/PDF document "Chat Application with ReactJS" is the property of its rightful owner. Permission is granted to download and print the materials on this web site for personal, non-commercial use only, and to display it on your personal computer provided you do not modify the materials and that you retain all copyright notices contained in the materials. By downloading content from our website, you accept the terms of this agreement.
Slide1
Chat Application withReactJS, Node.js and Socket.IO
Giuseppe AttardiCode: https://github.com/attardi/ReactJS-Realtime-Chat
http://
danialk.github.io
/blog/2013/06/16/
reactjs
-and-socket-dot-
io
-chat-application/Slide2
app.jsvar
app = express();var server = require('http').Server(app);// Socket.io
Communicationvar
io
= require('
socket.io
').listen(server);
var
socket = require('./routes/
socket.js
');
io.sockets.on
('connection', socket);
// Configuration
app.use
(
express.static
(__
dirname
+ '/public
'));
app.set
('port', 3000);
//
Start
server
server.listen
(
app.get
(
'port'));Slide3
Application ComponentsChatAppUserListMessageList
MessageMessageFormChangeNameFormSlide4
index.html<!
doctype html><html lang="en">
<head>
<title>
ReactJS
Socket.io
Chat Application</title
>
<meta charset="utf-8
">
<
link
rel
="stylesheet"
href
="
css
/
style.css
">
</
head
>
<
body
>
<div id="app"><div
/>
<script
src
="/
socket.io
/
socket.io.js
"></script
>
<script
src
="
js
/
app.js
"></script
>
</
body
>
</
html>Slide5
UserListvar UsersList =
React.createClass({ render() { return ( <div className='users'> <h3> Online
Users </h3> <ul> {
this.props.users.map
((
user
,
i
) =>
{
return
(<
li
key
={
i
}>
{
user
}</
li
>);
})
}
</
ul
>
</
div
>
);
}Slide6
MessageListvar
MessageList = React.createClass({ render() { return
( <div className='messages
'>
<h2> Conversation: </h2
>
{
this.props.messages.map
((message,
i
) =>
{
return
(
<
Message
key={
i
}
user={
message.user
}
text={
message.text
}
/>
);
})
}
</div
>
);
}});Slide7
Messagevar
Message = React.createClass({ render() { return ( <div className
="message"> <strong>{this.props.user} :</strong> <span>{this.props.text
}</span> </div>
);
}});Slide8
MessageForm
var MessageForm = React.createClass({ getInitialState
() { return {text: ''}; },
handleSubmit
(e)
{
e.preventDefault
();
var
message =
{
user :
this.props.user
,
text :
this.state.text
}
this.props.onMessageSubmit
(message
);
this.setState
({ text: ''
});
},
changeHandler
(e)
{
this.setState
({
text :
e.target.value
});
},
render()
{
return
(
<div
className
='
message_form
'>
<h3>Write New Message</h3
>
<form
onSubmit
={
this.handleSubmit
}>
<
input
onChange
={
this.changeHandler
}
value
={
this.state.text
}/>
</form
>
</div
>
);
}});Slide9
ChangeNameFormvar ChangeNameForm =
React.createClass({ getInitialState() { return {newName: ''}; }, onKey(e) { this.setState({ newName : e.target.value }); }, handleSubmit
(e) { e.preventDefault(); var newName = this.state.newName;
this.props.onChangeName
(
newName
);
this.setState
({
newName
: ''
});
},
render()
{
return(
<div
className
='
change_name_form
'>
<h3> Change Name </h3
>
<form
onSubmit
={
this.handleSubmit
}>
<
input
onChange
={
this.onKey
}
value
={
this.state.newName
}
/>
</form
>
</div
>
);
}});Slide10
ChatAppvar
ChatApp = React.createClass({ getInitialState() {
return {users: [], messages:[], text: ''};
},
componentDidMount
() {
socket.on
('
init
',
this._initialize
);
socket.on
('
send:message
',
this
._
messageRecieve
);
socket.on
('
user:join
', this._
userJoined
);
socket.on
('
user:left
', this._
userLeft
);
socket.on
('
change:name
',
this
._
userChangedName
);
},Slide11
MessageReceive_messageRecieve
(message) { var {messages} = this.state; messages.push
(message); this.setState({messages}); },Slide12
UserJoined_
userJoined(data) { var {users, messages} = this.state;
var {name} = data; users.push
(name);
messages.push
({
user: 'APPLICATION BOT
',
text:
name +'
Joined’
});
this.setState
({users, messages
});
},Slide13
UserLeft_
userLeft(data) { var {users, messages} = this.state;
var {name} = data;
var
index =
users.indexOf
(name
);
users.splice
(index, 1
);
messages.push
({
user: 'APPLICATION BOT
',
text:
name +'
Left’
});
this.setState
({users, messages
});
},Slide14
handleMessageSubmithandleMessageSubmit
(message) { var {messages} = this.state; messages.push
(message); this.setState
({messages
});
socket.emit
('
send:message
', message
);
},Slide15
handleChangeNamehandleChangeName
(newName) { var oldName =
this.state.user; socket.emit
('
change:name
',
{ name
:
newName
},
(result) =>
{
if (!result)
{
return alert
(’Error
changing your name
');
}
var
{users} =
this.state
;
var
index =
users.indexOf
(
oldName
);
users.splice
(index,
1,
newName
);
this.setState
({users, user:
newName
});
});
},Slide16
Renderrender() {
return ( <div> <UsersList users={this.state.users}/> <MessageList messages={this.state.messages}/> <MessageForm
onMessageSubmit={this.handleMessageSubmit} user={this.state.user
}
/>
<
ChangeNameForm
onChangeName
={
this.handleChangeName
}
/>
</
div
>
);
}});Slide17
In the render function, we use our components and assign their properties like html attributes which
are obtained from a react expression.Inside the expressions we use the main data that come from backend, eg users and messages, and are in ChatApp’s state.Slide18
routes/socket.js// export function for listening to the socket
module.exports = function (socket) { var name = userNames.getGuestName(); // send the new user their name and a list of users socket.emit('init', {
name: name, users: userNames.get() }); // notify other clients that a new user has
joined
socket.broadcast.emit
('
user:join
',
{
name: name
});
// broadcast a user's message to other
users
socket.on
('
send:message
', function (data)
{
socket.broadcast.emit
('
send:message
',
{
user: name
,
text:
data.text
});
});
Closures
for dealing with user namesSlide19
userName closures// Keep track of which names are used so that there are no
duplicatesvar userNames = (function () { var
names = {}; // find the lowest unused "guest" name and claim
it
var
getGuestName
= function ()
{
var
name,
nextUserId
= 1
;
do
{
name = 'Guest ' +
nextUserId
;
nextUserId
+= 1
;
} while (!claim(name
));
return name
;
};Slide20
var
claim = function (name) { if (!name || names[name]) { return false;
} else {
names[name] = true
;
return true
;
}
v
ar
free =
…
Var
get =
…
return
{
getGuestName
:
getGuestName
,
claim: claim
,
free: free
,
get:
get
};
}());Slide21
// validate a user's name change, and broadcast it on
success socket.on('change:name', function (data, fn) {
if (userNames.claim(
data.name
))
{
var
oldName
= name
;
userNames.free
(
oldName
);
name =
data.name
;
socket.broadcast.emit
('
change:name
',
{
oldName
:
oldName
,
newName
:
name
});
fn
(true
); // invoke callback
} else
{
fn
(false
); // invoke callback
}
});Slide22
On disconnect// clean up when a user leaves, and broadcast it to other
users socket.on('disconnect', function () { socket.broadcast.emit('
user:left', {
name: name
});
userNames.free
(name
);
});Slide23
Running We render the ChatApp and in the app
div, using React.renderReact.render(<ChatApp/>
, document.getElementById
('app'));