Flux
Get Started
https://facebook.github.io/flux/
Framework
BUKAN
Lupakan MVC Sejenak
https://medium.com/code-cartoons/a-cartoon-guide-to-flux-6157355ab207
Cartoon Introduction to Flux
Real Time Flux Chat
+ socket.io
Real Time Flux Chat
buat file js/actions/ChatAppAction.js
var ChatAppDispatcher = require('../dispatcher/ChatAppDispatcher');
var $ = require('jquery');
var ChatStore = require('../stores/ChatStore');
var ChatAppAction = {
sendMessage: function(data){
ChatAppDispatcher.handleAction({
type: 'RECEIVE_NEW_MESSAGE',
message: data
});
},
login: function(user){
ChatAppDispatcher.handleAction({
type: 'USER_LOGIN',
user: user
});
},
logout: function(){
ChatAppDispatcher.handleAction({
type: 'USER_LOGOUT',
user: ChatStore.getCurrentUser()
});
}
};
module.exports = ChatAppAction;
Real Time Flux Chat
buat file js/dispatcher/ChatAppDispatcher.js
var assign = require('object-assign');
Dispatcher = require('flux').Dispatcher;
var ChatAppDispatcher = assign(new Dispatcher(), {
handleAction: function(action){
this.dispatch({
action: action
});
}
});
module.exports = ChatAppDispatcher;
Real Time Flux Chat
buat file js/stores/ChatStore.js
var assign = require('object-assign');
var EventEmitter = require('events').EventEmitter;
var ChatAppDispatcher = require('../dispatcher/ChatAppDispatcher');
_currentUser = null;
_allUsers = [];
_messagesBag = [];
var CHANGE_EVENT = 'change';
var ChatStore = assign({}, EventEmitter.prototype, {
// penting
addChangeListener: function(callback){
this.on(CHANGE_EVENT, callback);
},
removeChangeListener: function(callback){
this.removeListener(CHANGE_EVENT, callback);
},
emitChange: function(){
this.emit(CHANGE_EVENT);
},
getCurrentUser: function(){
return _currentUser;
},
getAllUsers: function(){
return _allUsers;
},
getAllMessage: function(){
return _messagesBag;
},
addMessage: function(message){
_messagesBag.push(message);
},
setCurrentUser: function(user){
_currentUser = user;
},
setAllUsers: function(users){
_allUsers = users;
}
});
ChatStore.dispatchToken = ChatAppDispatcher.register(function(payload){
var action = payload.action;
switch (action.type) {
case 'USER_LOGIN':
ChatStore.setCurrentUser(action.user);
ChatStore.setAllUsers([action.user]);
ChatStore.emitChange();
break;
case 'USER_LOGOUT':
ChatStore.setCurrentUser(null);
ChatStore.setAllUsers([]);
ChatStore.emitChange();
break;
case 'RECEIVE_NEW_MESSAGE':
if(action.message.text == ''){
return;
}
ChatStore.addMessage(action.message);
ChatStore.emitChange();
break;
default:
// do nothing
}
});
module.exports = ChatStore;
Real Time Flux Chat
update file js/components/ChatApp.react.js
var React = require('react');
var PropTypes = React.PropTypes;
var Header = require('./Header.react');
var FriendList = require('./FriendList.react');
var MessageBox = require('./MessageBox.react');
var LoginBox = require('./Login.react');
var ChatStore = require('./../stores/ChatStore');
var ChatAppAction = require('./../actions/ChatAppAction');
getStateFromStore = function(){
return {
messagesBag: ChatStore.getAllMessage(),
currentUser: ChatStore.getCurrentUser(),
allUsers: ChatStore.getAllUsers()
};
};
var ChatApp = React.createClass({
getInitialState: function(){
return getStateFromStore();
},
componentDidMount: function(){
ChatStore.addChangeListener(this._onChange);
},
componentWillUnmount: function(){
ChatStore.removeChangeListener(this._onChange);
},
_onChange: function(){
this.setState(getStateFromStore());
},
render: function() {
if(!this.state.currentUser){
return (
<div className="chat-app">
<Header />
<LoginBox />
</div>
)
}
return (
<div className="chat-app">
<Header user={this.state.currentUser} />
<FriendList users={this.state.allUsers} />
<MessageBox
messages={this.state.messagesBag}
/>
</div>
);
}
});
module.exports = ChatApp;
User Join Room
(LOGIN)
Real Time Flux Chat
update file js/components/Login.react.js
var React = require('react');
var ChatAppAction = require('../actions/ChatAppAction');
var Login = React.createClass({
joinRoom: function(e){
e.preventDefault();
ChatAppAction.login({
username: this.refs.username.value
});
},
render: function() {
return (
<div className="login-box">
<form onSubmit={this.joinRoom}>
<input type="text" placeholder="Masukan nama panggilan kamu" ref="username"/>
</form>
</div>
);
}
});
module.exports = Login;
User Sends Message
Real Time Flux Chat
update file js/components/ComposeMessage.react.js
var React = require('react');
var PropTypes = React.PropTypes;
var ChatAppAction = require('../actions/ChatAppAction');
var ChatStore = require('../stores/ChatStore');
var ComposeMessage = React.createClass({
sendMessage: function(e){
e.preventDefault();
ChatAppAction.sendMessage({
author: ChatStore.getCurrentUser().username,
text: this.refs.messageText.value
});
this.refs.messageText.value = '';
},
render: function() {
return (
<div className="compose-message">
<form onSubmit={this.sendMessage}>
<input type="text" placeholder="kirim pesan" ref="messageText"/>
</form>
</div>
);
}
});
module.exports = ComposeMessage;
User Logout
Real Time Flux Chat
update file components/Header.react.js
var React = require('react');
var Header = React.createClass({
logout: function(){
ChatAppAction.logout();
},
render: function() {
logoutButton = '';
if(this.props.user){
logoutButton = (<a className="logout-btn" onClick={this.logout}>logout</a>)
}
return (
<div className="header">
<h2>Chat App</h2>
{logoutButton}
<hr />
</div>
);
}
});
module.exports = Header;
Socket.io
Real Time Flux Chat
update file stores/ChatStore.react.js
var assign = require('object-assign');
var EventEmitter = require('events').EventEmitter;
var ChatAppDispatcher = require('../dispatcher/ChatAppDispatcher');
_currentUser = null;
_allUsers = [];
_messagesBag = [];
var io = require('socket.io-client');
var CHANGE_EVENT = 'change';
var ChatStore = assign({}, EventEmitter.prototype, {
addChangeListener: function(callback){
this.on(CHANGE_EVENT, callback);
},
removeChangeListener: function(callback){
this.removeListener(CHANGE_EVENT, callback);
},
emitChange: function(){
this.emit(CHANGE_EVENT);
},
getCurrentUser: function(){
return _currentUser;
},
getAllUsers: function(){
return _allUsers;
},
getAllMessage: function(){
return _messagesBag;
},
addMessage: function(message){
_messagesBag.push(message);
},
setCurrentUser: function(user){
_currentUser = user;
},
setAllUsers: function(users){
_allUsers = users;
}
});
var socket = io();
socket.on('user_login', function(user){
ChatStore.addMessage({author: 'system', text: user.username + ' has joined the room'});
ChatStore.emitChange();
});
socket.on('user_logout', function(user){
ChatStore.addMessage({author: 'system', text: user.username + ' has left the room'});
ChatStore.emitChange();
});
socket.on('users_list_change', function(users){
ChatStore.setAllUsers(users);
ChatStore.emitChange();
});
socket.on('receive_new_message_from_server', function(message){
if(message.text == ''){
return;
}
ChatStore.addMessage(message);
ChatStore.emitChange();
});
ChatStore.dispatchToken = ChatAppDispatcher.register(function(payload){
var action = payload.action;
switch (action.type) {
case 'USER_LOGIN':
socket.emit('user_login', action.user);
ChatStore.setCurrentUser(action.user);
ChatStore.emitChange();
break;
case 'USER_LOGOUT':
socket.emit('user_logout', action.user);
ChatStore.setCurrentUser(null);
ChatStore.setAllUsers([]);
ChatStore.emitChange();
break;
case 'RECEIVE_NEW_MESSAGE':
socket.emit('receive_new_message', action.message);
if(action.message.text == ''){
return;
}
ChatStore.emitChange();
break;
default:
// do nothing
}
});
module.exports = ChatStore;
Real Time Flux Chat
untuk diamati: server.js
var express = require('express');
var app = express();
var lowdb = require('lowdb');
// var db = lowdb('server/db/todos.json');
var bodyParser = require('body-parser');
var cors = require('cors');
var uuid = require('uuid');
var assign = require('object-assign');
var _ = require('lodash');
app.use(bodyParser.json()); // for parsing application/json
app.use(bodyParser.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded
app.use(cors());
app.use(express.static(__dirname+'/'));
app.get('/', function(req, res) {
res.sendFile(__dirname + '/index.html');
});
var server = app.listen(7067, function(){
console.log('listening at 7067');
});
var users = [];
var io = require('socket.io').listen(server);
io.on('connection', function(socket){
socket.on('user_login', function(user){
users.push(user);
io.emit('user_login', user);
io.emit('users_list_change', users);
});
socket.on('user_logout', function(user){
usersList = _.remove(users, function(u){
return u.username == user.username;
});
io.emit('user_logout', user);
io.emit('users_list_change', users);
});
socket.on('receive_new_message', function(message){
io.emit('receive_new_message_from_server', message);
});
});
Real Time Flux Chat
untuk diamati: actions/ChatAppAction.js
var ChatAppDispatcher = require('../dispatcher/ChatAppDispatcher');
var $ = require('jquery');
var ChatStore = require('../stores/ChatStore');
var ChatAppAction = {
sendMessage: function(data){
ChatAppDispatcher.handleAction({
type: 'RECEIVE_NEW_MESSAGE',
message: data
});
},
login: function(user){
ChatAppDispatcher.handleAction({
type: 'USER_LOGIN',
user: user
});
},
logout: function(){
ChatAppDispatcher.handleAction({
type: 'USER_LOGOUT',
user: ChatStore.getCurrentUser()
});
}
};
module.exports = ChatAppAction;
Real Time Flux Chat
untuk diamati: stores/ChatStore.js
var assign = require('object-assign');
var EventEmitter = require('events').EventEmitter;
var ChatAppDispatcher = require('../dispatcher/ChatAppDispatcher');
_currentUser = null;
_allUsers = [];
_messagesBag = [];
var CHANGE_EVENT = 'change';
var ChatStore = assign({}, EventEmitter.prototype, {
// penting
addChangeListener: function(callback){
this.on(CHANGE_EVENT, callback);
},
removeChangeListener: function(callback){
this.removeListener(CHANGE_EVENT, callback);
},
emitChange: function(){
this.emit(CHANGE_EVENT);
},
getCurrentUser: function(){
return _currentUser;
},
getAllUsers: function(){
return _allUsers;
},
getAllMessage: function(){
return _messagesBag;
},
addMessage: function(message){
_messagesBag.push(message);
},
setCurrentUser: function(user){
_currentUser = user;
},
setAllUsers: function(users){
_allUsers = users;
}
});
ChatStore.dispatchToken = ChatAppDispatcher.register(function(payload){
var action = payload.action;
switch (action.type) {
case 'USER_LOGIN':
ChatStore.setCurrentUser(action.user);
ChatStore.setAllUsers([action.user]);
ChatStore.emitChange();
break;
case 'USER_LOGOUT':
ChatStore.setCurrentUser(null);
ChatStore.setAllUsers([]);
ChatStore.emitChange();
break;
case 'RECEIVE_NEW_MESSAGE':
if(action.message.text == ''){
return;
}
ChatStore.addMessage(action.message);
ChatStore.emitChange();
break;
default:
// do nothing
}
});
module.exports = ChatStore;
Flux at Detikcom
By Muhammad Azamuddin
Flux at Detikcom
- 870