-
Chat App with ReactJS, Socket.io #12018~2019/React.js 2018. 10. 7. 17:31
ReactJS로 Chat App 만들기 #1
(출처 : https://www.youtube.com/watch?v=84GXJANOYFw)
1. create-react-app react-chat
2. npm install socket.io uuid concurrently nodemon
1) socket.io : 웹 소켓을 활용한 라이브러리.
2) uuid : 범용 고유 식별자 (고유 식별 번호), RFC 4122스펙으로 정해져 있으며, 생성할 때 특별한 알고리즘을 이용하여 생성함.
3) concurrently : command 여러 개 실행.
4) nodemon : node.js에서 파일이 수정될 경우 자동으로 서버를 재시동함.
3. package.json 수정
"scripts": {"start": "concurrently 'npm run react' 'npm run server'","react": "react-scripts start","server": "nodemon src/server/index.js","build": "react-scripts build","test": "react-scripts test","eject": "react-scripts eject"},4. react-chat/src/server/index.js 생성
- 서버 생성 및 소켓 연결
var app = require('http').createServer();var io = module.exports.io = require('socket.io')(app);const PORT = process.env.PORT || 8080;const SocketManager = require('./SocketManager');io.on('connection', SocketManager);app.listen(PORT, () => {console.log("Connected to port:"+PORT);});5. react-chat/src/Events.js 생성
- 웹 소켓 이벤트 정의
module.exports = {COMMUNITY_CHAT: "COMMUNITY_CHAT",USER_CONNECTED: "USER_CONNECTED",MESSAGE_RECIEVED: "MESSAGE_RECIEVED",MESSAGE_SENT: "MESSAGE_SENT",USER_DISCONNECTED: "USER_DISCONNECTED",TYPING: "TYPING",VERIFY_USER: "VERIFY_USER",LOGOUT: "LOGOUT",}6. react-chat/src/server/SocketManager.js 생성
- 웹 소켓 이벤트 연결
1) VERIFY_USER : 닉네임 중복 체크
2) USER_CONNECTED : 유저 연결
3) LOGOUT : 유저 연결 해제
const io = require('.').io;const { VERIFY_USER, USER_CONNECTED, LOGOUT } = require('../Events');const { createUser, createMessage, createChat } = require('../Factories');const connectedUsers = { }module.exports = function(socket) {console.log("Socket ID :"+socket.id);socket.on(VERIFY_USER, (nickname, callback) => {if(isUser(connectedUsers, nickname)) {callback({isUser: true, user: null})}else {callback({isUser: false, user: createUser({name: nickname})})}});socket.on(USER_CONNECTED, (user) => {connectedUsers = addUser(connectedUsers, user);socket.user = user;console.log(connectedUsers);});}function addUser(userList, user) {let newList = Object.assign({}, userList);newList[user.name] = user;return newList;}function removeUser(userList, username) {let newList = Object.assign({}, userList);delete newList[username];return newList;}function isUser(userList, username) {return username in userList;}7. react-chat/src/server/Factories.js 생성
- 객체 정의
const uuidv4 = require('uuid/v4');const createUser = ({name = ""} = {}) => ({id: uuidv4(),name})const createMessage = ({message = "", sender = ""} = {}) => ({id: uuidv4(),time: getTime(new Date(Date.now())),message,sender,})const createChat = ({messages = [], name = "Community", users = []} = {}) => ({id: uuidv4(),name,messages,users,typingUsers: [],})const getTime = (date) => {return `${date.getHours()}:${("0"+date.getMinutes()).slice(-2)}`;}module.exports = {createMessage,createChat,createUser}7. react-chat/src/App.js 수정
- Chat App Layout 구현
import React, { Component } from 'react';import Layout from './components/Layout';import './App.css';class App extends Component {render() {return (<Layout title="React Chat App"/>);}}export default App;7. react-chat/src/components/Layout.js 수정
- 웹 소켓 연결 및 유저 등록
import React, { Component } from 'react';import io from 'socket.io-client';import { USER_CONNECTED, LOGOUT } from '../Events';import LoginForm from './LoginForm';const socketURL = "http://localhost:8080";class Layout extends Component {constructor(props) {super(props);this.state = {socket: null,user: null,};}componentWillMount() {this.initSocket();}initSocket = () => {const socket = io(socketURL);socket.on('connect', () => {console.log('connected...');});this.setState({socket});}setUser = (user) => {const { socket } = this.state;socket.emit(USER_CONNECTED, user);this.setState({user});}logout = () => {const { socket } = this.state;socket.emit(LOGOUT);this.setState({user: null,});}render() {const { socket } = this.state;const { title } = this.props;return (<div className="container">{title}<LoginForm socket={socket} setUser={this.setUser} /></div>);}}export default Layout;8. react-chat/src/components/LoginForm.js 수정
- 부모 컴포넌트(Layout.js)에서 전달받은 props(socket, setUser)를 통해 닉네임 중복 체크 후, 유저 등록
import React, { Component } from 'react';import { VERIFY_USER } from '../Events';class LoginForm extends Component {constructor(props) {super(props);this.state = {nickname: "",error: "",};}setUser = ({user, isUser}) => {console.log(user, isUser);if(isUser) {this.setError("User name taken");}else {this.props.setUser(user);this.setError("");}}setError = (error) => {this.setState({error});}handleSubmit = (e) => {e.preventDefault();const { socket } = this.props;const { nickname } = this.state;socket.emit(VERIFY_USER, nickname, this.setUser);}handleChange = (e) => {this.setState({nickname: e.target.value,});}render() {const { nickname, error } = this.state;return (<div className="login"><form onSubmit={this.handleSubmit} className="login-form"><label htmlFor="nickname"><h2>Got a nickname?</h2></label><input type="text" ref={(input) => {this.textInput = input}} id="nickname" value={nickname} onChange={this.handleChange} placeholder={'UserName'}/><div className="error">{error ? error : null}</div></form></div>);}}export default LoginForm;'2018~2019 > React.js' 카테고리의 다른 글
MobX 예제 - 슈퍼마켓 만들기 (0) 2018.10.18 MobX (0) 2018.10.14 6. React와 Express, MongoDB 연동하기 - Socket.io (0) 2018.10.06 5. React와 Express, MongoDB 연동하기 (4) UPDATE (0) 2018.10.06 4. React와 Express, MongoDB 연동하기 (3) DELETE (0) 2018.10.05