동작에 대한 기록 저장
slice()를 사용해 매 동작 이후에 squares 배열의 새로운 복사본을 만들었고 이를 불변 객체로 취급했음.
이를 통해 과거의 squares배열의 모든 버전을 저장하고 이미 지나간 차례를 탐색할 수 있다.
const handleClick = (i) => {
const newSquares = squares.slice(); // slice로 통째 복사
과거의 squares 배열들을 history라는 다른 배열에 저장할 것이며,
history배열은 첫 동작부터 마지막 동작까지 모든 게임판의 상태를 아래같이 표현.
이전 동작에 대한 리스트를 보여주려면 최상위 단계의 App 컴포넌트가 필요.
App 컴포넌트에 history state를 이동.
state를 App컴포넌트로 이동
const App = () => {
const [history, setHistory] = useState([{squares: Array(9).fill(null)}]);
const [xIsNext, setXIsNext] = useState(true);
승자(winner)상태와 계산하는 함수도 App 컴포넌트로 이동
const calcWiner = (squares) => {
const winner = calcWiner(current.squares);
현 상태를 가지고 있는 state 추가
const current = history[history.length - 1]
handleClick함수를 App 컴포넌트로 이동
App컴포넌트의 state가 다르게 구성되어 있기에 수정해야 함.
새로운 기록 목록을 history로 연결.
const newSquares = current.squares.slice();
if(calcWiner(newSquares) || newSquares[i]) {
return;
}
newSquares[i] = xIsNext? "X" : "O";
setHistory([...history, {squares: newSquares}]); // 전개 연산자 사용. 하단에 추가설명
setXIsNext(prev => !prev);
}
App컴포넌트에 있는 함수와 state를 Board 컴포넌트에 전달
App.js
승자상태 (state)도 상위 컴포넌트 App.js에서 처리.
return (
<div className="game">
<div className="game-board">
<Board squares={current.squares} onClick={(i)=> handleClick(i)} />
</div>
<div className="game-info">
<div className="state">{status}</div>
</div>
</div>
)
Board컴포넌트에서 props 받고 처리
Board.js
const Board = ({squares,onClick}) => {
const renderSquare = (i) => {
return (
<Square
value={squares[i]}
onClick={() => onClick(i)} />
)
}
전개 연산자 (Spread Operator)
ECMAScript6 (2015)에서 새롭게 추가.
특정 객체나 배열의 값을 다른 객체, 배열로 복제하거나 옮길 때.
연산자의 모양은 '...'
배열 조합
객체 조합
보통의 조합은 "객체 자체가 들어간다"
전개연산자를 사용하면, 각각의 값이 할당된다.
기존 배열 보존