본문 바로가기
개발

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

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

튜토리얼(Tutorial) - 10



앞선 포스팅에서 틱택토 그리드에 버튼을 클릭할 때 마다 히스토리를 저장했다.

이렇게 저장한 히스토리를 호출하여 움직임으로 보여주고, 해당 시점으로 이동하는 기능을 추가해보자



움직임 보여주기


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
  render() {
    const history = this.state.history;
    const current = history[history.length - 1];
    const winner = calculateWinner(current.squares);
 
    const moves = history.map((step, move) => {
      const desc = move ?
        'Move #' + move :
        'Game start';
      return (
        <li>
          <a href="#" onClick={() => this.jumpTo(move)}>{desc}</a>
        </li>
      );
    });
 
    let status;
    if (winner) {
      status = 'Winner: ' + winner;
    } else {
      status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
    }
 
    return (
      <div className="game">
        <div className="game-board">
          <Board
            squares={current.squares}
            onClick={(i) => this.handleClick(i)}
          />
        </div>
        <div className="game-info">
          <div>{status}</div>
          <ol>{moves}</ol>
        </div>
      </div>
    );
  }
cs


지금까지 게임 중에 만들어진 동작들을 보여주는 기능을 추가해보자.

리액트 엘리먼트는 자바스크립트 일급객체와 동일하게 취급되므로 값을 저장하거나 전달할 수 있다.

리액트에서는 여러 항목을 랜더링 하기위해 리액트 엘리먼트의 배열을 전달 한다.

배열을 만드는 가장 일반적인 방법은 데이터 배열을 매핑(map 메소드를 사용해서)하는 것이다.


Game의 render메소드에서 이를 구현할 수 있다.

히스토리의 각 단계 마다 아무것도 없는 <a>태그가 포함된 <li>리스트를 만들고

곧 구현한 클릭 핸들러를 넣어준다.




시점 이동 구현


1
2
3
4
5
6
7
8
9
10
    const moves = history.map((step, move) => {
      const desc = move ?
        'Move #' + move :
        'Game start';
      return (
        <li key={move}>
          <a href="#" onClick={() => this.jumpTo(move)}>{desc}</a>
        </li>
      );
    });
cs


히스토리의 각 단계마다 고유의 구분되어지는 key값을 설정한다.

바로 이동 되어진 횟수이다.

따라서 <li> 태그 안에 key값으로 {move}값을 넣어준다




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Game extends React.Component {
  constructor() {
    super();
    this.state = {
      history: [{
        squares: Array(9).fill(null),
      }],
      stepNumber: 0,
      xIsNext: true,
    };
  }
 
  jumpTo(step) {
    this.setState({
      stepNumber: step,
      xIsNext: (step % 2) ? false : true,
    });
  }
 
cs


우선 constructor에 stepNumber라는 새로운 state를 추가해준다.

이 state는 현재 보고 있는 step이 어디인지 알려주는 역할을 한다.


또한 jumpTo를 구현하지 않았으므로 Game 컴포넌트 안에 구현해 준다.

이때 중요한 것은 이전으로 돌아가기 때문에 X/O에 대한 순서도 재설정할 필요가 있는데,

스텝이 짝수이면 xIsNext를 true로 설정한다.




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  handleClick(i) {
    const history = this.state.history.slice(0, this.state.stepNumber + 1);
    const current = history[history.length - 1];
    const squares = current.squares.slice();
    if (calculateWinner(squares) || squares[i]) {
      return;
    }
    squares[i] = this.state.xIsNext ? 'X' : 'O';
    this.setState({
      historyhistory.concat([{
        squares: squares
      }]),
      stepNumber: history.length,
      xIsNext: !this.state.xIsNext,
    });
  }
cs


그리고 클릭이 일어날 때마다 stepNumber를 업데이트 시켜야한다.

또한 랜더링은 이러한 StepNumber를 기준으로 이루어진다.

이를 위해서 handleClick 메소드를 위와 같이 수정해주도록 하자




1
2
3
4
5
6
  render() {
    const history = this.state.history;
    const current = history[this.state.stepNumber];
    const winner = calculateWinner(current.squares);
 
    // the rest has not changed
cs

마지막으로 render 메소드 안에 current값을 추가해 줌으로써 해당 단계를 읽을수 있게 된다.
이로써 이동 링크를 클릭하면 보드가 즉시 업데이트 되어 해당 시점으로 돌아가는 기능까지 추가되었다.

이 과정까지 진행 하면 틱택토 게임의 어드밴스 기능까지 완료된 것이다.


반응형

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

[Raspberry] 정적 IP 할당  (0) 2017.06.11
[Raspberry] 맥에 라즈비안 OS 설치  (0) 2017.06.11
[ReactJS] 튜토리얼(Tutorial) - 9  (0) 2017.06.11
[ReactJS] 튜토리얼(Tutorial) - 8  (0) 2017.06.10
[ReactJS] 튜토리얼(Tutorial) - 7  (0) 2017.06.10

댓글