GameBoard.tsx 3.01 KB
import React, { useCallback, useContext, useEffect, useState } from 'react';
import { useLocation } from 'react-router';
import SocketContext from '../../contexts/SocketContext';
import { MessageType, RawMessage } from '../common/types';
import Canvas from './Canvas';
import RoundInfo from './RoundInfo';
import { RoundData } from './types';
import Word from './Word';

interface GameBoardLocation {
  state: { username: string }
}

interface GameBoardProps {
  isInGame: boolean
}

const GameBoard: React.FC<GameBoardProps> = ({ isInGame }) => {
  const socket = useContext(SocketContext);
  const location: GameBoardLocation = useLocation();

  const [ isDrawer, setIsDrawer ] = useState(false);
  const [ words, setWords ] = useState<string[]>([]);
  const [ wordChosen, setWordChosen ] = useState('');
  const [ round, setRound ] = useState(0);

  const handleWordSet = useCallback((rawMessage: RawMessage) => {
    if (rawMessage.type === MessageType.GAME_WORDSET) {
      console.log('단어 도착');
      const { words } = rawMessage.message as { words: string[] };
      setWords(words);
    }
  }, []);

  const handleStart = useCallback((rawMessage: RawMessage) => {
    if (rawMessage.type === MessageType.GAME_START) {
      setWords([]);

      const data = rawMessage.message as RoundData;
      // console.log(location.state.username);
      // console.log(data.roles);
      const index = data.roles.findIndex(x => x.username === location.state.username);
      setIsDrawer(data.roles[index].role === 'drawer');
      setWordChosen('');
      setRound(data.round);
    }
  }, []);

  const handleGetWordLength = useCallback((rawMessage: RawMessage) => {
    if (rawMessage.type === MessageType.GAME_WORD) {
      if (wordChosen === '') {
        const { length } = rawMessage.message as { length: number };
        setWordChosen('_' + ' _'.repeat(length-1));
      }
    }
  }, [wordChosen]);

  const handleAnswer = useCallback((rawMessage: RawMessage) => {
    if (rawMessage.type === MessageType.GAME_ACCEPT || rawMessage.type === MessageType.GAME_FINISH_ROUND) {
      const { answer } = rawMessage.message as { answer: string };
      setWordChosen(answer);
    }
  }, []);

  useEffect(() => {
    socket.on('msg', handleStart);
    socket.on('msg', handleWordSet);
    socket.on('msg', handleAnswer);

    return () => {
      socket.off('msg', handleStart);
      socket.off('msg', handleWordSet);
      socket.off('msg', handleAnswer);
    }
  }, []);

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

  return (
    <div className={`w-auto ${isInGame ? '' : 'hidden'}`}>
      <div className='w-full flex flex-col justify-center items-center'>
      {words.map((word, i) => (<Word key={word} index={i} word={word} setWordChosen={setWordChosen} setWords={setWords} />))}
      </div>
      <Canvas isDrawer={isDrawer && wordChosen !== ''} />
      <RoundInfo round={round} wordChosen={wordChosen} />
    </div>
  );
}

export default GameBoard;