리액트 가위바위보 게임 만들기

hhkim·2021년 7월 27일
0
post-thumbnail

🔗 react-rockpaperscissors 완성본

웹 게임을 만들며 배우는 React에서 실습했던 내용을 토대로 다시 만들어보는 가위바위보 게임


프로젝트 세팅

  • create-react-app 프로젝트 생성
    npx create-react-app react-rockpaperscissors

코드 작성

이미지를 쓰지 않아서 강의보다는 조금 간단하게 코드를 작성해보았다.

  • 오브젝트의 키를 동적으로 받으려면 오브젝트명[키]를 사용한다.
  • 유저가 버튼을 클릭하고 1초 동안 멈춘 사이에 다시 버튼을 클릭하는 반칙을 저지르지 않게 하기 위해 buttondisabled 속성을 주었다.
    👉 state에 btnDisabled를 추가하고 버튼을 클릭하면 true 값을 주었다가 다시 재개가 될 때 false로 변경되도록 하였다.
import React, { useState, useRef, useEffect, useCallback } from 'react';

const scores = {
  '✊': 1,
  '✋': 0,
  '✌': -1,
};

const RPS = () => {
  const [computer, setComputer] = useState('✊');
  const [user, setUser] = useState('🤘');
  const [result, setResult] = useState('');
  const [score, setScore] = useState(0);
  const [btnDisabled, setBtnDisabled] = useState(false);
  const interval = useRef(null);

  const changeHand = useCallback(() => {
    if (computer === '✊') {
      setComputer('✋');
    } else if (computer === '✋') {
      setComputer('✌');
    } else if (computer === '✌') {
      setComputer('✊');
    }
  }, [computer]);

  const onClickBtn = (user) => () => {
    setUser(user);
    setBtnDisabled(true);
    clearInterval(interval.current);
    const diff = scores[user] - scores[computer];
    if (diff === 0) {
      setResult('draw');
    } else if ([-1, 2].includes(diff)) {
      setResult('win');
      setScore((prevScore) => prevScore + 1);
    } else {
      setResult('lose');
      setScore((prevScore) => prevScore - 1);
    }
    setTimeout(() => {
      interval.current = setInterval(changeHand, 100);
      setBtnDisabled(false);
    }, 1000);
  };

  useEffect(() => {
    interval.current = setInterval(changeHand, 100);
    return () => {
      clearInterval(interval.current);
    };
  }, [changeHand]);

  return (
    <div>
      <div>{computer}</div>
      <div>{result}</div>
      <div>{user}</div>
      <div>
        <button disabled={btnDisabled} onClick={onClickBtn('✊')}>
          Rock
        </button>
        ...
      </div>
      <div>Score: {score}</div>
    </div>
  );
};

export default RPS;

useCallback()

참고
렌더링 시 성능을 최적화하기 위해 사용하는 함수

  • 함수형 컴포넌트는 렌더링마다 임의 메서드를 다시 재생성하는데, 이걸 useCallback()으로 감싸고 종속성을 지정하면, 해당 종속성이 변경될 때만 새로운 함수를 생성하도록 한다. (함수의 레퍼런스를 기억하게 함)
  • 그래서 useEffect()의 종속성으로 useCallback() 함수를 사용하면 의존성 해결 완료....
    (나 같은 경우 ESLint가 useEffect() 안에 state를 변경하는 함수를 썼으니까 종속성에 함수를 추가하고 함수는 useCallback()으로 감싸라길래 그렇게 했다.... 어려워 🤪)

0개의 댓글