튜토리얼(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({       history: history.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 | 
'개발' 카테고리의 다른 글
| [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 | 
댓글