-
[React] React Docs해석하면서 공부하기 2장 Tic-Tac-ToeReact 2023. 3. 8. 01:52
개요
React Docs의 Tic-Tac-Toe를 만들어보면서 React에 대한 내용을 공부하며 스스로 정리해보자.
1. 초기 코드
필요한 파일은 App.js, index.js, styles.css과 pulic폴더가 필요하다.
App.js 에서는 컴포넌트를 생성합니다.
React의 컴포넌트는 사용자 인터페이스의 일부를 표시하는 재사용이 가능한 코드조각입니다.
우선 Square함수를 정의하고 X가 표시된 버튼을 만들어 봅시다.
export default function Square() { return <button className="square">X</button>; }
export키워드를 사용한다면 파일 외부에서 이 함수에 접근이 가능합니다.
default키워드를 사용한다면 다른파일에서 이 함수가 주요한 함수임을 알려줍니다.
return 뒤의 코드는 함수호출자에게 값으로 반환됩니다.
<button>은 JSX Element입니다. JavaScript코드와 HTML태그의 조합으로 표시할 내용을 설명합니다.
className="square"은 버튼의 prop또는 프로퍼티입니다. CSS에 스타일을 지정하는 방법을 알려줍니다.index.js는 App.js에서 만든 컴포넌트와 웹 브라우저사이의 다리역할을 합니다.
보드 만들기
이제 본격적으로 tic-tac-toe를 만들어봅시다.
App.js에서 x버튼을 하나 만들어 보았습니다.
하지만 우리는 총 9개의 버튼이 필요합니다. 제일 단순한 방법으로 복붙으로 해결해 봅시다!
export default function Square() { return <button className="square">X</button><button className="square">X</button>; }
이렇게 코드를 작성한다면 우리는 오류를 만나게 될 것입니다.
/src/App.js: Adjacent JSX elements must be wrapped in an enclosing tag. Did you want a JSX fragment <>...</>?
이유는 React컴포넌트는 항상 단일 JSX엘리먼트를 반환해줘야 합니다.
이 문제를 해결하기 위해서는 fragments를 사용하여 JSX를 래핑해준다면 해결할 수 있습니다.
(참고: https://beta.reactjs.org/reference/react/Fragment)
자 이제 x가 두개인 버튼이 생성됩니다.
자 이제 9개의 버튼을 복붙한다면 일렬로 된 x가 나타납니다.
우리는 한줄로된 버튼이 필요한 것이 아닌 3x3형태가 필요합니다.
해결하기 위해서 우린 CSS클래스를 추가하여 해결해봅시다.
export default function Square() { return ( <> <div className="board-row"> <button className="square">1</button> <button className="square">2</button> <button className="square">3</button> </div> <div className="board-row"> <button className="square">4</button> <button className="square">5</button> <button className="square">6</button> </div> <div className="board-row"> <button className="square">7</button> <button className="square">8</button> <button className="square">9</button> </div> </> ); }
위와 같이 코드를 작성했다면 좋은 결과물을 보여지게 됩니다.
이 함수는 더이상 사각형(square)를 뜻하지 않기에 함수명도 Board로 변경해줍시다!
Props로 데이터를 전달하기
이제 값이 비어있는 상태에서 x로 변경하는 것을 구현하고 싶습니다.
하지만 하나하나 복붙하는 행위말고 좀 더 스마트한 방법을 구상해봅시다!
React의 컴포넌트 아키텍처를 사용한다면 재사용한 컴포넌트를 만들어 중복된 코드를 해결할 수 있습니다.
우선 우리가 만든 Board컴포넌트에서 첫 번째 사각형을 정의하는 코드를 새롭게 Square라는 함수를 만들어봅시다.
function Square() { return <button className="square">1</button>; } export default function Board() { // ... }
이후 Board컴포넌트를 JSX 문법을 사용하여 Square컴포넌트를 렌더링하게 만들어볼까요?
// ... export default function Board() { return ( <> <div className="board-row"> <Square /> <Square /> <Square /> </div> <div className="board-row"> <Square /> <Square /> <Square /> </div> <div className="board-row"> <Square /> <Square /> <Square /> </div> </> ); }
여기서 포인트는 컴포넌트명은 항상 대문자로 시작해야합니다!
자 우리의 결과물은 1이 9개가 만들어진 버튼이 나올 것입니다.
다음 단계는 1이 아닌 우리가 원하는 값이 나오길 바랍니다.
function Square()에 value를 전달해 봅시다.
function Square({ value }) { return <button className="square">1</button>; }
function Square({value}) 는 사각형 컴포넌트에 value라는 prop을 전달이 가능합니다.
이제 1 대신 원하는 value값을 표시해야합니다.
여기서 중요한 점은 바로 "이스케이프문"인 {}을 활용하는 것입니다.
JSX에서는 JavaScript로 이스케이프하기 위해서는 중괄호를 사용합니다.
function Square({value}) { return <button className="square">{value}</button> }
위 코드를 적용한다면 빈 보드가 보일 것입니다.
그 이유는 Square컴포넌트에 아직 value prop을 전달하지 않았기 때문입니다.
Square컴포넌트에 value prop을 추가해봅시다.
export default function Board() { return ( <> <div className="board-row"> <Square value="1" /> <Square value="2" /> <Square value="3" /> </div> <div className="board-row"> <Square value="4" /> <Square value="5" /> <Square value="6" /> </div> <div className="board-row"> <Square value="7" /> <Square value="8" /> <Square value="9" /> </div> </> ); }
이제 숫자가 나타난 보드가 나타납니다.
최종코드
https://codesandbox.io/embed/keen-ellis-w6zwff?fontsize=14&hidenavigation=1&theme=dark&module=/App.js&editorsize=70&view=split
상호작용하는 컴포넌트 작성하기
이제부터는 컴포넌트를 클릭한다면 X로 채워지는 방법을 만들어보겠습니다.
Square내부에 handleClick이라는 함수를 선언후 JSX의 props에 onClick을 추가해줍니다.
function Square({ value }) { function handleClick() { console.log('clicked!'); } return ( <button className="square" onClick={handleClick} > {value} </button> ); }
이제 사각형을 클릭한다면 Console에 "clicked!"가 표시됩니다.
useState
컴포넌트가 클릭된 것을 기억하기 위해서는 state를 사용합니다.
React는 컴포넌트에서 무엇을 호출하여 "기억"할 수 있는 useState라는 함수를 제공합니다.
이제 컴포넌트에서 value prop을 제거하고 useState를 사용해 봅시다.
import {useState} from 'react'; function Square() { const [value, setValue] = useState(null); function handleClick() {~~~} }
useState코드 줄을 해석해보면 value는 값을 저장하고 setValue는 값을 변경하는데 사용되는 함수 입니다.
useState에 전달된 null은 상태변수의 초기값으로 사용이 되며 value는 null입니다.
Square컴포넌트의 value prop도 제거하고 Square가 클릭되었을 때 "X"를 표시하도록 변경을 해봅시다.
function Square() { const [value, setValue] = useState(null); function handleClick() { setValue('X'); } return ( <button className="square" onClick={handleClick} > {value} </button> ); } export default function Board() { return ( <> <div className="board-row"> <Square /> <Square /> <Square /> </div> <div className="board-row"> <Square /> <Square /> <Square /> </div> <div className="board-row"> <Square /> <Square /> <Square /> </div> </> ); }
onClick핸들러에서 set함수를 호출한다. 이제 <button>이 클릭될때마다 Square가 재렌더링인됩니다.
Square의 value인 값은 "X"이므로 클릭을 한다면 X가 보여질 것입니다.
정리
이번 챕터에서는 각 파일에 대해서 분석하며 알아보았고 컴포넌트의 개념, props에 대한 공부, useState를 활용하여 상호작용되는 컴포넌트를 만들어 보았습니다.
다음 챕터에서는 tic-tac-toe을 활용하여 state를 끌어올려 해결하는 방법, 불변성 등에 대한 공부를 해보겠습니다.
'React' 카테고리의 다른 글
[React] React Docs해석하면서 공부하기 4장 React로 사고하기 (0) 2023.03.23 [React] React Docs해석하면서 공부하기 3장 Tic-Tac-Toe (0) 2023.03.16 [React] React Docs해석하면서 공부하기 1장 (1) 2023.03.05 [React] React Docs해석하면서 공부하기 (0) 2023.03.02