Room.tsx 3.21 KB
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 { Canvas } from '../components/room/Canvas';
import { Chat } from '../components/room/Chat';
import { RoomInfo } from '../components/room/RoomInfo';
import { RoomData, UpdateRoomUser } from '../components/room/types';
import { UserInfo } from '../components/room/UserInfo';
import { UserStatus } from '../components/room/UserStatus';
import SocketContext from '../contexts/SocketContext';

interface RoomLocation {
  state: { roomData: RoomData }
}

export 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 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.indexOf(data.user);
        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);
    }
  }, [roomData]);

  useEffect(() => {
    // 비정상적인 루트로 방을 들어오면 로그인 화면으로 푸시
    if (location.state === undefined) {
      history.push('/');
      return;
    }

    setRoomData(location.state.roomData);

    return () => {
      const rawMessage: RawMessage = {
        type: MessageType.ROOM_LEAVE,
        message: ''
      }
      socket.emit('msg', rawMessage, (response : MessageResponse<undefined>) => {});
    }
  }, [])
  
  return (
    <Main>
      <RoomInfo roomData={roomData}/>
      {
        isInGame ? (
          <div className='w-full flex'>
            <Canvas />
            <Chat w='w-4/12' h='h-80' />
          </div>
        ) : (
          <div className='w-full flex flex-col justify-center items-center'>
            <UserInfo users={roomData.users}/>
            <Chat w='w-7/12' h='h-96' />
          </div>
        )
      }
    </Main>
  );
}