사용자 도구

사이트 도구


react:tictactoe

차이

문서의 선택한 두 판 사이의 차이를 보여줍니다.

차이 보기로 링크

양쪽 이전 판이전 판
다음 판
이전 판
react:tictactoe [2018/08/02 04:43] – [Keys] taekgureact:tictactoe [2025/04/15 10:05] (현재) – 바깥 편집 127.0.0.1
줄 681: 줄 681:
 <li>Ben: 5 tasks left</li> <li>Ben: 5 tasks left</li>
 </code> </code>
 +
 +<code javascript>
 +<li>Ben: 9 tasks left</li>
 +<li>Claudia: 8 tasks left</li>
 +<li>Alexa: 5 tasks left</li>
 +</code>
 +사람의 눈에는 Alexa와 Ben의 자리가 바뀌고 Claudia가 추가된 것처럼 보인다. 하지만 React는 단순한 컴퓨터프로그램이므로 여러분의 의도를 알지 못합니다. React는 리스트의 각 요소에서 key속성을 지정해달라고 요청합니다. 문자열은 형제로부터 각 컴포넌트들을 구분합니다. 이 경우에 alexa, ben, claudia는 구분할 수 있는 키가 됩니다. 만약 아이템들이 데이터베이스의 객체와 일치시켜야 한다면 데이터베이스 ID를 사용하세요.
 +<code javascript>
 +<li key={user.id}> {user.taskCount} tasks left</li>
 +</code>
 +
 +key는 React에서 제공되는 특별한 속성입니다(ref에서 더 확장된 기능). 엘리먼트가 만들어질때 React는 key속성을 가져오고 반환된 엘리먼트에 직접적으로 key를 저장합니다. key가 props의 한 부분으로 보일지라도 이것은 this.props.key로 참조할 수 없습니다. React는 어떤 하휘 엘리먼트가 수정될지 결정하는 동안 알아서 key를 사용합니다. 컴포넌트가 자신의 키를 알 수 있는 방법은 없습니다.
 +
 +리스트가 랜더링될 때 React는 새로운 버전의 각 엘리먼트를 가져오고 이전 리스트에서 매칭되는 키를 가진 것을 찾습니다. key가 세트에 추가될 때 컴포넌트는 만들어집니다. 키가 삭제될 때 컴포넌트는 소멸됩니다. 키들은 React가 각 요소를 구별할 수 있도록하여 다시 랜더링하는 것을 무시하고 상태를 유지할 수 있게 합니다. 만약 컴포넌트의 키를 바꾼다면 완전히 지운 후 새롭게 생성됩니다.
 +
 +**동적으로 리스트를 빌드할 때마다 적당한 키를 할당할 것을 강력 추천합니다.** 만약 적당한 키를 가지지 못한다면 이를 위해 데이터를 재구성하여야 할지도 모릅니다.
 +
 +특정한 키를 구분하지 못한다면 React는 경고를 주고 배열 인덱스를 키로 사용합니다. 이는 올바른 선택이 아닙니다. 만약 리스트에 있는 엘리먼트들을 정렬하거나 리스트에 있는 버튼을 통해 지우거나 추가하면 명시적으로 key={i}를 전달하는 방법을 사용한다면 경고를 표시하지는 않지만 동일한 문제를 발생시키므로 대부분의 경우에는 추천하지 않습니다.
 +
 +컴포넌트의 키가 전부 다를 필요는 없지만 관련있는 현제들 사이에서는 유니크해야 합니다.
 +
 +==== 시간 여행 실행하기 ====
 +이동 리스트르ㅡ 위해 우리는 각 단계에서 유니크ID를 가졌습니다. Game의 render메서드에서 키는 <li key={move}>로 추가하면 경고는 표시되지 않습니다.
 +<code javascript>
 +        const moves = history.map((step, move) => {
 +            const desc = move?'Go to move #' + move : 'Go to game startg';
 +            return (
 +                <li key={move}>
 +                  <button onclick={()=>this.jumpTo(move)}>{desc}</button>
 +                </li>
 +            );
 +        });
 +</code>
 +지금까지의 코드는 [[https://codepen.io/gaearon/pen/PmmXRE?editors=0010|이곳]]에서 보실 수 있습니다.
 +
 +아직 jumpTo가 정의되지 않았기 때문에 이동 버튼을 클릭하면 에러가 발생합니다. 지금 표시된 단계가 무엇인지 알기 위해 Game상태에 새로운 키를 추가해봅시다.
 +
 +먼저 Game의 constructor에 stepNumber: 0를 추가해주세요.
 +<code javascript>
 +  class Game extends React.Component {
 +    constructor(props) {
 +      super(props);
 +      this.state = {
 +        history: [{
 +          squares: Array(9).fill(null)
 +        }],
 +        stepNumber: 0,
 +        xIsNext: true,
 +      };
 +    }
 +</code>
 +그 다음 각 상태를 업데이트하기 위해 Game의 jumpTo메서드를 정의해봅시다. 이 메서드에서는 xlsNext를 업데이트하고, 이동의 인덱스가 짝수라면 xlsNext를 true로 설정합니다.
 +
 +Game클래스에 jumpTo메서드를 추가해주세요.
 +
 +<code javascript>
 +    handleClick(i) {
 +        // this method has not changed
 +    }
 +    jumpTo(step) {
 +        this.setState({
 +            stepNumber: step,
 +            xlsNext: (step % 2) === 0,
 +        })
 +    }
 +    render() { // this method has not changed }
 +</code>
 +Game handleClick에 상태를 업데이트하기 위해 stepNumber:history.length를 추가하여 새로운 이동이 있을 때마다 stepNumber를 업데이트합니다. 현재 보드의 상태를 읽을 때 handleClick이 stepNumber라고 보고 클릭하는 시간대로 상태를 되돌릴 수 있습니다.
 +
 +<code javascript>
 +    handleClick(i) {
 +      const history = this.state.history;
 +      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,
 +      });
 +    }
 +</code>
 +
 +이제 히스토리의 각 단계를 알기 위해 Game의 render를 수정할 수 있습니다.
 +
 +<code javascript>
 +    render() {
 +        const history = this.state.history;
 +        const current = history[this.state.stepNumber];
 +        const winner = calculateWinner(current.squares);
 +        // the rest has not changed
 +</code>
 +
 +지금까지의 코드는 [[https://codepen.io/gaearon/pen/gWWZgR?editors=0010|이곳]]에서 보실 수 있습니다.
 +
 +이제 이동 버튼을 클릭하면 보드는 즉시 그때 표시된 게임으로 변경됩니다.
 +
 +==== 마무리 ====
 +틱택토 게임을 플레이 해보세요.
 +  * 틱택토 게임을 플레이 해보세요.
 +  * 한 명의 플레이어가 게임에서 이길 때 이를 알려줍니다.
 +  * 게임이 진행되는 동안 이동 기록이 저장됩니다.
 +  * 게임 보드의 에전 버전을 표시하기 위해 시간을 되돌릴 수 있습니다.
 +
 +잘 동작하네요! React가 어떻게 동작하는지 잘 아셨기를 바랍니다.
 +
 +최종 결과물은 [[https://codepen.io/gaearon/pen/gWWZgR?editors=0010|여기]]에서 확인하세요.
 +
 +**시간이 더 있거나 새로운 스킬들을 연습해보고 싶다면 해볼 수 있는 몇 가지 아이디어가 있습니다. 점점 더 어려운 순으로 배치해두었습니다.**
 +
 +  - 움직임 리스트에서 (col,row)형태에 각 움직임 위치를 표시하세요.
 +  - 움직임 리스트의 선택된 아이템을 볼드처리하세요.
 +  - 하드코딩한 것들 대신 사각형을 두 개의 루프를 사용하여 Board를 다시 작성하세요.
 +  - 오름차순 혹은 내림차순 뭐든지 움직임을 정렬하는 버튼을 추가해보세요.
 +  - 누군가 이겼을 때 무엇 때문에 이겼는지 세 개의 사각형을 하이라이트하세요.
 +
 +튜토리얼이 진행되는 동안 우리는 엘리먼트, 컴포넌트, props, 상태를 포함한 React의 수많은 컨셉들을 다뤘습니다. 각 주제에 대한 깊은 설명을 원한다면 [[https://reactjs.org/docs/hello-world.html|남은문서]]를 확인하세요. 컴포넌트정의에 대해 더 많이 배우고 싶다면 [[https://reactjs.org/docs/react-component.html|이 문서]]를 확인하세요.
 +
react/tictactoe.1533184992.txt.gz · 마지막으로 수정됨: 2025/04/15 10:05 (바깥 편집)