Room.tsx
3.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import React, { useCallback, useContext, useEffect, useState } from 'react';
import { useHistory, useLocation } from 'react-router';
import Main from '../components/common/Main';
import { MessageResponse, MessageType, RawMessage } from '../components/common/types';
import Chat from '../components/room/Chat';
import GameBoard from '../components/room/GameBoard';
import Ready from '../components/room/Ready';
import RoomInfo from '../components/room/RoomInfo';
import { RoomData, UpdateRoomUser } from '../components/room/types';
import UserInfo from '../components/room/UserInfo';
import UserRole from '../components/room/UserRole';
import SocketContext from '../contexts/SocketContext';
interface RoomLocation {
state: { roomData: RoomData }
}
const Room: React.FC = () => {
const history = useHistory();
const socket = useContext(SocketContext);
const location: RoomLocation = useLocation();
const [ roomData, setRoomData ] = useState<RoomData>({
// 기본값
uuid: '0',
name: 'loading...',
maxUsers: 9,
users: []
});
const [ isInGame, setIsInGame ] = useState(false);
const handleInGame = useCallback((rawMessage: RawMessage) => {
if (rawMessage.type === MessageType.GAME_START) {
setIsInGame(true);
} else if (rawMessage.type === MessageType.GAME_FINISH_GAME) {
setIsInGame(false);
}
}, []);
const handleUpdateRoomUser = useCallback((rawMessage: RawMessage) => {
if (rawMessage.type === MessageType.ROOM_USER_UPDATE) {
const data = rawMessage.message as UpdateRoomUser;
if (data.state === 'removed') {
const newUsers = roomData.users;
const index = newUsers.findIndex(x => x.username === data.user.username);
if (index < 0) {
console.log('존재하지 않는 유저를 제거 시도');
} else {
newUsers.splice(index, 1);
}
setRoomData({
...roomData,
users: newUsers
});
} else if (data.state === 'updated') {
const newUsers = roomData.users;
const index = newUsers.findIndex(x => x.username === data.user.username);
if (index < 0) {
console.log('존재하지 않는 유저를 업데이트 시도');
} else {
newUsers[index] = data.user;
}
setRoomData({
...roomData,
users: newUsers
})
} else {
setRoomData({
...roomData,
users: [data.user, ...roomData.users]
});
}
}
}, [roomData]);
useEffect(() => {
socket.on('msg', handleUpdateRoomUser);
return () => {
socket.off('msg', handleUpdateRoomUser);
}
}, [handleUpdateRoomUser]);
useEffect(() => {
// 비정상적인 루트로 방을 들어오면 로그인 화면으로 푸시
if (location.state === undefined) {
history.push('/');
return;
}
setRoomData(location.state.roomData);
socket.on('msg', handleInGame);
return () => {
socket.off('msg', handleInGame);
const rawMessage: RawMessage = {
type: MessageType.ROOM_LEAVE,
message: ''
}
socket.emit('msg', rawMessage, (response : MessageResponse<undefined>) => {});
}
}, [location.state]);
return (
<Main>
<RoomInfo roomData={roomData}/>
<div className='w-full flex justify-center'>
{/* 게임보드와 유저롤을 계속 살려둬서 리스너를 항상 열어놓도록 하자 */}
<UserRole isInGame={isInGame} />
<GameBoard isInGame={isInGame} />
{
isInGame ? (
<Chat w='w-4/12' h='h-132' />
) : (
<div className='w-full flex flex-col justify-center items-center'>
<UserInfo users={roomData.users}/>
<Ready users={roomData.users} />
<Chat w='w-7/12' h='h-96' />
</div>
)
}
</div>
</Main>
);
}
export default Room;