지난 게시글에서는
board 컴포넌트에 상태를 선언하고,
setState로 상태 변경을 감지한 후,
Square컴포넌트로 onClick 이벤트를 작동시킬 함수를 props로 전달하였다.
이번 게시글에서는,
- state값 props로 전달해서 버튼 클릭 시 'X' 또는 'O' 렌더링
- 한번 클릭한 버튼을 재클릭할 수 없도록 하기
를 해볼 것이다.
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>
'React > 4.TicTacToe 게임 만들기' 카테고리의 다른 글
틱택토6. 승자 결정하기 (0) | 2022.04.23 |
---|---|
틱택토4. 컴포넌트 작성(2) (0) | 2022.04.22 |
틱태토3. 컴포넌트 작성(1) (0) | 2022.04.21 |
틱택토2. TicTacToe 게임의 명세 (0) | 2022.04.21 |
틱택토1. 레이아웃 및 CSS 셋팅 (0) | 2022.04.21 |
댓글