Chat Application - ReactJs
8/8/25About 2 min
ReactJs:
Để đơn giản và dễ dàng tiếp cận react thì mình dùng functional component (Mình code chính là backend, frontend thì có làm qua Vue và Angular) và cùng với hổ trợ của React hooks.
Ahthentication: Redux
Chat realtime: Socket.io client
CSS library: Ant design
Chat library: react-chat-elements
Authentication:
authReducer
import { LOGIN, LOGOUT } from '../ActionTypes';
const authInit = JSON.parse(localStorage.getItem('currentUser'));
export default (state = authInit, action) => {
switch (action.type) {
case LOGIN:
return action.payload;
case LOGOUT:
return {};
default:
return state;
}
};
authService
import { createStore } from 'redux';
import { LOGIN, LOGOUT } from '../ActionTypes';
import { postApi, postApiFormData } from './api';
import authReducer from '../reducers/auth';
// Create store
const authStore = createStore(authReducer);
const login = (data) => postApi('login', data).then((userData) => {
localStorage.setItem('currentUser', JSON.stringify(userData));
authStore.dispatch({
type: LOGIN,
payload: userData,
});
return userData;
});
const register = (data) => postApiFormData('register', data);
const logout = () => {
localStorage.removeItem('currentUser');
authStore.dispatch({
type: LOGOUT,
});
};
export const auth = {
login,
register,
logout,
get currentUser() { return authStore.getState(); },
};
Middleware Route:
import { Redirect, Route } from 'react-router-dom';
import React from 'react';
import { auth } from '../../services/auth';
const PrivateRoute = ({ component: Component, ...rest }) => (
<Route
{...rest}
render={(props) => {
if (!auth.currentUser) {
return <Redirect to={{ pathname: '/login' }} />;
}
return <Component {...props} />;
}}
/>
);
export default PrivateRoute;
const App = () => (
<Router>
<Switch>
<PublicRoute path="/register" component={Register} />
<PublicRoute path="/login" component={Login} />
<PrivateRoute path="/" component={ChatContainer} />
</Switch>
</Router>
);
SocketIo Client:
Khởi tại io client với endpoint và authenticate token
import io from 'socket.io-client';
// API_ENDPOINT = 'http://localhost:5000/'
export default function ChatContainer() {
useEffect(() => {
// Create socket
const user = auth.currentUser;
socket = io(config.API_ENDPOINT, {
query: {
token: user.token,
},
});
}, []);
}
Listen socket room
: khi 1 room mới được thêm, server socket sẽ gửi dữ liệu room này đến các client đang listen. Client nhận dữ liệu và thêm vào danh sách room.
/* server */
// .....
socket.broadcast.emit(`rooms`, room);
// .....
/* client */
socket.on('rooms', (roomOn) => {
const message = roomOn.messages[0] || {
avatar: '',
text: '',
};
store.dispatch({
type: PUSH_ROOM,
payload: {
_id: roomOn._id,
avatar: `${config.API_ENDPOINT}${message.user.avatar}`,
alt: roomOn.name,
title: roomOn.name,
subtitle: message.text,
unread: 1,
date: new Date(),
},
});
// .....
});
Send message: Client emit
const sendMessage = (roomId, message) => {
if (message) {
socket.emit('sendMessage', { roomId, message });
}
};
Message được gửi đến room, server sẽ nhận và gửi lại cho các client đang lắng nge chanel.
/* server */
io.to(roomId).emit(`message:${roomId}`, messageEmit);
Series: