본문 바로가기
React/4.TicTacToe 게임 만들기

틱택토5. 컴포넌트 작성(3)

by 혀닙 2022. 4. 23.

지난 게시글에서는

board 컴포넌트에 상태를 선언하고,

setState로 상태 변경을 감지한 후,

Square컴포넌트로 onClick 이벤트를 작동시킬 함수를 props로 전달하였다.

 

 

이번 게시글에서는,

  1. state값 props로 전달해서 버튼 클릭 시 'X' 또는 'O' 렌더링
  2. 한번 클릭한 버튼을 재클릭할 수 없도록 하기

를 해볼 것이다.

 

 

 

 

 

 

1. state값 props로 전달해서 버튼 클릭 시 'X' 또는 'O' 렌더링

 

버튼엘리먼트의 내부의 value props로 전달할 수 있도록하는 코드 부터 시작해보자.

지난 게시글에서 squares 변수를 선언하여 handleClick 안에서 작성해두었기 때문에

 

간단히,

renderSquare 함수 안의 Square 컴포넌트로 보낼 props인 value의 값을 아래와 같이 state의 squares로 변경하면 된다.

 

<Square 
    value = {this.state.squares[i]}
    onClick = { ()=> {this.handleClick(i)} }
/>

 

 

위의 코드를 작성해주면 아래와 같이 버튼을 눌렀을 때 'O' 또는 'X'가 표시된다.

 

 

 

 

 

하지만 아직까지는 동일한 버튼을 재클릭할 수 없다는 게임의 규칙에 위반된다.

 

 

 

<게임 명세 참고>

https://yellow-w.tistory.com/222?category=1039072 

 

 

 

2. 한번 클릭한 버튼을 재클릭할 수 없도록 하기

 

 

지금까지 작성된 코드대로라면 기본적으로 squares는 null값이며,

이미 한번 클릭된 squares는 O 또는 X의 값을 가질 것이다.

 

따라서, 다음과 같은 간단한 한줄의 코드를 작성해보자.

if( squares[i] != null )return;

 

해당 코드는

  • i번 squares의 값이 null이 아닌 경우
  • 즉 'X' 또는 'O'의 값을 가질 경우
  • 다시 말해 한번이라도 클릭된 경우

handleClick 함수를 빠져나가는 코드이다.

 

위의 코드의 위치는

변수 선언과 squares[i]의 값 할당의 사이에 위치하여야 한다.

 

 

 

 

 

3. 지금까지 작성한 코드(누적)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link type = "text/css" href = "./game.css" rel = "stylesheet">
    <script crossorigin src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
    <div id = "root"></div>
    <script type ="text/babel">
    
        class Square extends React.Component {
            render() {
                return(
                    <button 
                        className="square"
                        onClick = {this.props.onClick}
                        >
                        {this.props.value}
                    </button>
                )
            }
        }

        class Board extends React.Component {
            state = {
                squares: Array(9).fill(null),
                xIsNext: true
            }

            handleClick = i =>{
                const squares = [...this.state.squares]
                const {xIsNext} = {...this.state}

                if(squares[i]!=null)return;

                squares[i] = xIsNext ? 'X' : 'O'

                this.setState({
                    squares,
                    xIsNext: !xIsNext
                })
            }

            renderSquare = i => {
                return(
                    <Square 
                        value = {this.state.squares[i]}
                        onClick = { ()=> {this.handleClick(i)} }
                        />
                )
            }
            render() {
                const { renderSquare } = this
                return(
                    <div>
                        <div className="status"></div>
                        <div className="board-row">
                            {renderSquare(0)}
                            {renderSquare(1)}
                            {renderSquare(2)}
                        </div>
                        <div className="board-row">
                            {renderSquare(3)}
                            {renderSquare(4)}
                            {renderSquare(5)}
                        </div>
                        <div className="board-row">
                            {renderSquare(6)}
                            {renderSquare(7)}
                            {renderSquare(8)}
                        </div>
                    </div>
                )
            }
        }

        class Game extends React.Component {
            render() {
                return(
                    <div>
                        <Board />
                    </div>
                )
            }
        }
    
        const root = document.querySelector('#root')
        ReactDOM.render(<Game />,root)
        
    </script>
</body>
</html>

댓글