저번 시간에 게임판 컴포넌트를 생성했고
이 격자를 동적으로 렌더링하였습니다
이제 이 버튼을 좀더 작업해 보고
이 게임판에 대한 상태(state)를 작업하여
변동사항이 적용될 수 있도록 하겠습니다
즉 UI를 업데이트하고
버튼을 누른 플레이어에게 지정되어 있는 기호가
클릭된 버튼에 뜨도록 하겠습니다
이것을 위해 게임판 컴포넌트에
새로운 상태를 추가해야 합니다
이 useState 훅(hook)을 사용하겠습니다
이전에 작업한 대로 리액트에서 가져와야 합니다
여기에서 만드는 상태의 목표는
게임판에 변동사항을 적용하는 것입니다
그러므로 이 initialGameBoard를
초깃값으로 가져와서 이 상태가
중첩 배열, 즉 다차원 배열이도록 설정하겠습니다
이 상태 상수를 gameBoard라고 이름짓고
이 업데이트 함수를 setGameBoard라고 하겠습니다
이제 함수를 하나 만들겠습니다
이 버튼을 클릭하면 반응하는 함수인데
이 상태를 업데이트하기 위해
setGameBoard의 도움을 받겠습니다
이 함수는 handleSelectSquare로 이름짓겠습니다
이름은 임의로 지으셔도 됩니다
이 함수가 작동될 때에
setGameBoard를 호출하여 이 게임판을
새로운 게임판으로 대체할 것입니다
버튼 하나가 null에서 X나 O로 바뀌어 있는 판입니다
어떤 기호인지는 어떤 플레이어가 눌렀느냐에 달려 있습니다
여기에서의 목표는
게임판을 업데이트하는데
게임판의 직전 상태에 기반하여 업데이트하는 것입니다
이전의 상태가 지속되도록 하는 것이 중요하기 때문입니다
이전에 선택되었던 필드에 대한
정보를 잃어버리지 않는 것이 중요합니다
이 배열의 필드 하나만 변경하는 것입니다
이제 여기에 함수 형식을 하나 사용해서
상태를 업데이트하게 만들겠습니다
즉, 이 함수를 상태 변경 함수로 전달하는 것입니다
여기의 인수는 prevGameBoard이고
이전에 배운 대로 리액트가 자동으로 전달합니다
이제 변경된 게임판을 반환해 보겠습니다
이 함수 바디(body)는
이 안쪽 함수에 있는 것으로, 목표는
이 안쪽 배열의 필드 하나를 X나 O로 대체하는 것입니다
이 handleSelectSquare에
정보가 몇 개 필요합니다
우리가 가지고 있는 행 인덱스를 알아야 하는데
즉 어떤 안쪽 배열이 업데이트되어야 하는 필드인지
혹은 어떤 안쪽 배열이 이 버튼을
렌더링하는 데 참여했는지
그리고 정확히 어떤 필드를 클릭했는지
즉 어떤 null값이 X나 O로 대체되어야 하는지
이 모든 것을 알아야 합니다
이 작업을 위해 colIndex를 사용하겠습니다
이제 열 하나와 행 하나에 대한 작업이 있습니다
그 다음 알아야 하는 것은
어떤 기호로 대체되는지, 즉 X인지 O인지 알아야 합니다
이 부분은 단순히 어떤 플레이어의 차례인지에 따라
정해지는 부분입니다
이 부분은 나중에 작업하겠습니다
이 내용에는 로직이 좀더 필요하기 때문입니다
현재로서는 일단 X로 지정해 놓겠습니다
이 인덱스 두 개로 확인된 필드에 지정하는 것입니다
이제 prevGameBoard 배열을 가지고
안쪽 배열 하나를 지정할 수 있습니다
이 때에는 rowIndex를 사용합니다
그리고 안쪽 배열의 요소 하나를
즉 null 값 중 하나를 지정하겠습니다
이렇게 함으로써
어떤 요소가 이 중첩 배열에 있는지 알 수 있습니다
이제 이것을 X로 대체한 후에
변경된 상태를 새로운 상태로서 반환하겠습니다
이렇게 할 수도 있습니다만
추천드리는 방식은 아닙니다
이 대신에 사용하셔야 하는 방식은
기존 상태에 기반해서 상태를 업데이트하기 위해
이 상태 업데이트 함수를 쓰듯이
만약 상태가 객체나 배열이라면
해당 상태를 업데이트할 때
변경 불가능하게 하는 것이 좋습니다
즉 이전 상태를 하나 복제해서 새 객체 또는 배열로 저장해 놓고
이 복제된 버전을 수정하는 방식입니다
원본 객체 또는 배열은 변경되지 않습니다
이 방식을 추천드리는 이유는
만약 상태가 객체 혹은 배열이라면
이는 자바스크립트 내의 참조 값입니다
그러므로 이런 방식으로 업데이트한다면
메모리 속의 기존 값을 바로 변경하게 되는데
이 시점은 리액트가 실행하는 예정된 상태 업데이트보다
이전에 일어나게 됩니다
그러므로 알 수 없는 버그나 부작용이 생길 수 있습니다
이것은 앱 내부의 한 상태에 대해
상태 업데이트가 여러 개 예정되어 있을 때 일어납니다
그러므로 이 참조 값에 대해
더 알고 싶다면
이 강의에 링크를 하나 첨부해 두겠습니다
그 링크로 들어가 보시면
이 중요한 자바스크립트 기능에 대해 더 배우실 수 있습니다
이 내용은 자바스크립트 개발자라면 꼭 알아야 하는 내용입니다
이 내용은 특히 지금과 같이
객체 혹은 배열 상태 값을 작업할 때 필요합니다
이제 해야 하는 일은
새로운 상수 혹은 변수를 만드는 것입니다
이름은 updatedBoard로 하겠습니다
이 배열 안에서 스프레드 연산자를 사용해
기존의 배열에 있던 요소를 보두 붙여넣겠습니다
이것은 메모리에 저장되는 새로운 배열 객체로서
기존 배열 요소를 자식 요소로서 저장하고 있습니다
이것이 배열 안의 배열 구조를 가지고 있으므로
이것 또한 업데이트와 동시에 모두 복사됩니다
이 작업을 통해서
기존 상태의 map 메소드를 이 기존의 배열에
불러올 수 있습니다
여기에 innerArray을 넣고
각 innerArray마다 중첩 배열 구조를 하나씩 가져와서
그 안의 innerArray 요소를 분배할 수 있습니다
말하자면 이 새로운 배열 안에는
새로운 중첩 배열이 가득 차 있고
이전에 저장한 데이터를 아직 가지고 있지만
이 변경된 게임판이 업데이트된 후에
반환되어야 합니다
이 방식과 패턴을 사용함으로써
이 상태를 변경 불가능한 방식으로 업데이트하는 것입니다
이것은 이미 언급한 이유로
강하게 추천드리는 방식입니다
이제 handleSelectSquare를 사용하여
이것을 버튼의 onClick 속성에 지정하겠습니다
여기에 행과 callIndex를 인수로 호출해야 하므로
이 위치인 handleSelectSquare에 이전에도 알려드렸던
유용한 방식을 하나 사용하겠습니다
여기에 이름 없는 함수를 하나 만들면
이 함수는 onClick의 값으로서 전달됩니다
즉 이제 handleSelectSquare가 호출되는 과정에 대해
완전한 통제가 가능해졌습니다
이 rowIndex와 callIndex를 인수로
handleSelectSquare에 전달하면
이 함수에 필요한 내용을 받을 수 있습니다
이제 게임판 상태를 제대로 변경할 수 있습니다
즉 기존 상태에 기반하여 변경하는 방식입니다
이제 아직 작업 중인 이 gameBoard 상태를
initialGameBoard 대신으로 사용하는 것입니다
즉 초기에만 initialGameBoard를 사용하고
이 상태는 이후에 변경되어
업데이트된 gameBoard로 대체됩니다
이대로 저장한 후에 확인해 보면
버튼을 눌러서 X를 만들 수 있습니다
현재로서는 이 게임에서 이길 수도 없고
다른 플레이어와 차례대로 게임을 진행할 수 없습니다
이번 시간에는 버튼을 눌러 상태를 업데이트하도록 작업했고
이 작업을 통해 만약 특정 상태가
객체나 배열에 영향을 받는다면
불변하는 방식으로 변경되어야 하는 것을 배웠습니다