RoomInfo.tsx 2.03 KB
import React, { useCallback, useContext, useEffect, useState } from 'react';
import { useLocation, useParams } from 'react-router';
import SocketContext from '../../contexts/SocketContext';
import { MessageResponse, MessageType, RawMessage } from '../common/types';
import { RoomData, UpdateRoomUser } from './types';

interface RoomInfoLocation {
  state: { roomData: RoomData }
}

export const RoomInfo: React.FC = () => {
  const socket = useContext(SocketContext);
  const location: RoomInfoLocation = useLocation();

  const [ roomData, setRoomData ] = useState<RoomData>({
    // 기본값
    uuid: '0',
    name: 'loading...',
    maxUsers: 9,
    users: []
  });

  const handleUpdateRoomUser = useCallback((rawMessage: RawMessage) => {
    if (rawMessage.type == MessageType.ROOM_USER_UPDATE) {
      const data = rawMessage.message as UpdateRoomUser;
      console.log(data);
      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 == 'added') {
        setRoomData({
          ...roomData,
          users: [data.user, ...roomData.users]
        });
      }
    }
  }, [roomData]);

  useEffect(() => {
    socket.on('msg', handleUpdateRoomUser);
    
    return () => {
      socket.off('msg', handleUpdateRoomUser);
    }
  }, [roomData]);

  useEffect(() => {
    setRoomData(location.state.roomData);

    return () => {
      const rawMessage: RawMessage = {
        type: MessageType.ROOM_LEAVE,
        message: ''
      }
      socket.emit('msg', rawMessage, (response : MessageResponse<undefined>) => {});
    }
  }, [])

  return (
    <div className='m-3 w-5/6 flex items-center place-content-between'>
      <div>{roomData.name}</div>
      <div>{roomData.users.length}/{roomData.maxUsers}</div>
    </div>
  );
}