본문 바로가기
개발

[ReactJS] 튜토리얼(Tutorial) - 8

by 마스터누누 2017. 6. 10.
728x90
반응형

튜토리얼(Tutorial) - 8



Functional Component


다시 틱택토 게임으로 돌아와서, 우리는 Square 컴포넌트의 constructor를 제거했었다.

이로인해서 Square는 내부에 뷰를 그려주는 render 메소드 하나만 남게 된다.

이렇게 render하나만 있는 단순화 된 컴포넌트를 위해서 

리액트는 functional component라는 문법을 지원해준다.


React.component를 확장하는 대신, 

props를 인자로 받고 랜더링 되는 값을 리턴하는 함수를 작성하는 것이다.



1
2
3
4
5
6
7
function Square(props) {
  return (
    <button className="square" onClick={props.onClick}>
      {props.value}
    </button>
  );
}
cs


Square 클래스는 변경되어 위의 함수와 같이 변한다.

먼저 Class가 function으로 변해야하며, this.props가 props로 바뀐다.

따라서 this.props.value와 this.props.onClick은 각각 props.value와 props.onClick으로 변경되었다.

만약 onClick뒤에 ()를 붙이면 즉시 동작하므로 이벤트 발생 때는 호출되지 않는다. 

리액트로 만드는 프로젝트의 많은 컴포넌트가 위와 같이 바뀔 수 있으며, 

이렇게 코드를 변경하면 향후에 더 많이 최적화 될수 있다.





순서 대로 플레이 하기


1
2
3
4
5
6
7
8
class Board extends React.Component {
  constructor() {
    super();
    this.state = {
      squares: Array(9).fill(null),
      xIsNext: true,
    };
  }
cs


현재까지 만들어진 틱텍토 게임의 단점은 X만 플레이 할 수 있다는 것이다. 

기존 게임 룰에 맞게 고치도록 하자.

우선 첫번째 기본 값을 'X'로 설정한다.

Board constructor에서 시작 상태를 수정하자


위의 코드에서 처럼 우리는 클릭 이벤트가 발생할 때 마다 부울값으로 선언된 xIsNext값을 판별한 후

그 값을 뒤집어서 상태를 저장한다



1
2
3
4
5
6
7
8
  handleClick(i) {
    const squares = this.state.squares.slice();
    squares[i] = this.state.xIsNext ? 'X' : 'O';
    this.setState({
      squares: squares,
      xIsNext: !this.state.xIsNext,
    });
  }
cs


다음으로 값을 판별하고 상태값을 적용한 후 뒤집는 코드를 만들어야한다.

모든 연산은 클릭이 일어난 후에 동작하므로 handleClick에 선언해 준다.

위의 코드 작성이 완료되면 클릭 시 X와 O값이 정상적으로 적용된다.




1
2
3
4
5
  render() {
    const status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
 
    return (
      // the rest has not changed
cs


다음은 Board에서 누가 할 차례인지 출력하게 만드는 코드이다.

3항 연산자를 이용하여 xIsNext 값에 맞추어 X 또는 O의 차례임을 표시한다.




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
class Board extends React.Component {
  constructor() {
    super();
    this.state = {
      squares: Array(9).fill(null),
      xIsNext: true,
    };
  }
 
  handleClick(i) {
    const squares = this.state.squares.slice();
    squares[i] = this.state.xIsNext ? 'X' : 'O';
    this.setState({
      squares: squares,
      xIsNext: !this.state.xIsNext,
    });
  }
 
  renderSquare(i) {
    return (
      <Square
        value={this.state.squares[i]}
        onClick={() => this.handleClick(i)}
      />
    );
  }
 
  render() {
    const status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
 
    return (
      <div>
        <div className="status">{status}</div>
        <div className="board-row">
          {this.renderSquare(0)}
          {this.renderSquare(1)}
          {this.renderSquare(2)}
        </div>
        <div className="board-row">
          {this.renderSquare(3)}
          {this.renderSquare(4)}
          {this.renderSquare(5)}
        </div>
        <div className="board-row">
          {this.renderSquare(6)}
          {this.renderSquare(7)}
          {this.renderSquare(8)}
        </div>
      </div>
    );
  }
}
cs


모든 변경이 끝나면 위와 같은 코드가 된다.





승리 판별


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function calculateWinner(squares) {
  const lines = [
    [012],
    [345],
    [678],
    [036],
    [147],
    [258],
    [048],
    [246],
  ];
  for (let i = 0; i < lines.length; i++) {
    const [a, b, c] = lines[i];
    if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
      return squares[a];
    }
  }
  return null;
}
cs


틱택토 게임이 끝나려면 누가 승리자인지 확인해야한다.

위 승리 판별 함수를 파일의 끝에 추가해 주도록 하자.

Board에서 랜더링 시 이 함수를 호출하여 누가 이겼는지 판별하고 이긴 사람이 있다면

상태 텍스트에 "Winner : [O/X]"라고 표시한다.




1
2
3
4
5
6
7
8
9
10
11
render() {
    const winner = calculateWinner(this.state.squares);
    let status;
    if (winner) {
      status = 'Winner: ' + winner;
    } else {
      status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
    }
 
    return (
      // the rest has not changed
cs


이를 위해서 Board의 랜더링에서 status를 다음과 같이 변경한다.




1
2
3
4
5
6
7
8
9
10
11
handleClick(i) {
    const squares = this.state.squares.slice();
    if (calculateWinner(squares) || squares[i]) {
      return;
    }
    squares[i] = this.state.xIsNext ? 'X' : 'O';
    this.setState({
      squares: squares,
      xIsNext: !this.state.xIsNext,
    });
  }
cs


게임이 끝난 경우 클릭을 무시해야한다.

handleClick에서 게임 승자를 판별하는 함수를 이용해 조건문을 추가해 줌으로써

만약 게임이 끝났다면 아무것도 하지 않고 리턴할 수 있게된다.

위의 코드를 추가 하면 게임이 끝나는 경우 더이상 틱택토 게임을 진행할 수 없다.


여기까지가 틱택토 게임을 완성하면서 살펴본 리액트의 기본 튜토리얼이었다.

반응형

'개발' 카테고리의 다른 글

[ReactJS] 튜토리얼(Tutorial) - 10  (0) 2017.06.11
[ReactJS] 튜토리얼(Tutorial) - 9  (0) 2017.06.11
[ReactJS] 튜토리얼(Tutorial) - 7  (0) 2017.06.10
[ReactJS] 튜토리얼(Tutorial) - 6  (0) 2017.06.10
[ReactJS] 튜토리얼(Tutorial) - 5  (0) 2017.06.10

댓글