์์ต์: React ์์ํ๊ธฐ
These docs are old and wonโt be updated. Go to react.dev for the new React docs.
The updated Tutorial teaches modern React and includes live examples.
์ด ์์ต์๋ React์ ๋ํ ์ด๋ค ์ง์๋ ๊ฐ์ ํ์ง ์์ต๋๋ค.
์์ต์๋ฅผ ์์ํ๊ธฐ ์ ์
์ฐ๋ฆฌ๋ ์ด ์์ต์์์ ์์ ๊ฒ์์ ๋ง๋ค๊ฒ๋๋ค. ๊ฒ์์ ๋ง๋ค๊ณ ์ถ์ง ์์์ ์์ต์๋ฅผ ๊ฑด๋๋ฐ๊ณ ์ถ์ ์ ์์ต๋๋ค. ๊ทธ๋๋ ํ๋ฒ ํด๋ณด์ธ์! ์์ต์๋ฅผ ํตํด React ์ฑ์ ๋ง๋๋ ๊ธฐ๋ณธ์ ์ธ ์ฌํญ๋ค์ ๋ฐฐ์๋๋ค. ์ด๊ฒ์ ๋ง์คํฐํ๋ฉด React๋ฅผ ๋ ๊น๊ฒ ์ดํดํ ์ ์์ต๋๋ค.
ํ
์์ต์๋ ์ค์ต์ผ๋ก ๋ฐฐ์ฐ๊ธฐ๋ฅผ ์ ํธํ๋ ์ฌ๋๋ค์ ๋ง์ถฐ ์ค๊ณ๋์์ต๋๋ค. ๊ธฐ์ด๋ถํฐ ๊ฐ๋ ์ ํ์ตํ๊ธธ ์ ํธํ๋ค๋ฉด ๋จ๊ณ๋ณ ๊ฐ์ด๋๋ฅผ ํ์ธํด๋ณด์ธ์. ์์ต์์ ๋จ๊ณ๋ณ ๊ฐ์ด๋๋ ์ํธ ๋ณด์์ ์ ๋๋ค.
์์ต์๋ ์๋์ ๊ฐ์ด ๋ช ๊ฐ์ง ๋ถ๋ถ์ผ๋ก ๋๋์ด ์์ต๋๋ค.
- ์์ต์ ํ๊ฒฝ์ค์ ์ ์์ต์๋ฅผ ๋ฐ๋ฅผ ์ ์๋ ์์์ ์ ์๋ดํฉ๋๋ค.
- ๊ฐ์์์๋ React์ ๊ธฐ๋ณธ(components, props, state)์ ๋ํด์ ์์๋ด ๋๋ค.
- ๊ฒ์ ์์ฑํ๊ธฐ๋ React ๊ฐ๋ฐ์์ ์ฌ์ฉํ๋ ๊ฐ์ฅ ์ผ๋ฐ์ ์ธ ํ ํฌ๋์ ๊ฐ๋ฅด์ณ ์ค ๊ฒ์ ๋๋ค.
- ์๊ฐ์ฌํ ์ถ๊ฐํ๊ธฐ๋ React์ ๊ณ ์ ํ ๊ฐ์ ์ ๋ํ ๊น์ ํต์ฐฐ๋ ฅ์ ์ค ๊ฒ์ ๋๋ค.
์์ต์๋ฅผ ์ตํ๊ธฐ ์ํด ๋ชจ๋ ๋ถ๋ถ์ ํ ๋ฒ์ ์๋ฃํ ํ์๋ ์์ต๋๋ค. ํ๋ ๊ตฌ์ญ์ด๋ผ๋ ๊ฐ๋ฅํ ํ ๋ง์ด ์๋ํด ๋ณด์ธ์.
์ด ์์ต์๋ฅผ ๋ฐ๋ผ ํ๊ธฐ ์ํด ์ฝ๋๋ฅผ ๋ณต์ฌํ์ฌ ๋ถ์ฌ๋ฃ๋ ๊ฒ๋ ๊ด์ฐฎ์ง๋ง ์ง์ ์ฝ๋๋ฅผ ๋ฐ๋ผ ์ ๊ธฐ๋ฅผ ์ถ์ฒํฉ๋๋ค. ์ด ๋ฐฉ์์ ๋ชธ์ผ๋ก ๊ธฐ์ตํ๋ ๊ฒ๊ณผ ๋ ๊ฐํ ์ดํด์ ๋์์ ์ค ๊ฒ์ ๋๋ค.
๋ฌด์์ ๋ง๋ค๊ฒ ๋ ๊น์?
์ฐ๋ฆฌ๋ React๋ก ๋ํํ ํฑํํ ๊ฒ์์ ๋ง๋๋ ๋ฐฉ๋ฒ์ ์๋ ค๋๋ฆด ๊ฒ์ ๋๋ค.
์ต์ข ๊ฒฐ๊ณผ๋ฌผ์ ์ด ํ์ด์ง์์ ํ์ธํ ์ ์์ต๋๋ค. ์ฝ๋๊ฐ ์ดํด๊ฐ ๋์ง ์๊ฑฐ๋ ์ฝ๋์ ๋ฌธ๋ฒ์ ์ต์ํ์ง ์๋๋ผ๋ ๊ฑฑ์ ๋ง์ธ์! ์์ต์์ ๋ชฉ์ ์ React์ React ๋ฌธ๋ฒ์ ๋ํ ์ดํด๋ฅผ ๋๋ ๊ฒ์ ๋๋ค.
์์ต์๋ฅผ ์งํํ๊ธฐ ์ ์ ํฑํํ ๊ฒ์์ ์ฒดํํด๋ณด๊ธธ ์ถ์ฒํฉ๋๋ค. ์ฃผ๋ชฉํ ๋งํ ํน์ง ์ค ํ๋๋ ๊ฒ์ํ ์ค๋ฅธ์ชฝ์ ๋ฒํธ๊ฐ ๋งค๊ฒจ์ง ๋ชฉ๋ก์ด ์๋ค๋ ๊ฒ์ ๋๋ค. ๋ชฉ๋ก์ ๊ฒ์์์ ์ผ์ด๋ ๋ชจ๋ ์ด๋์ ๊ธฐ๋ก์ ๋ณด์ฌ์ฃผ๋ฉฐ ๊ฒ์์ ์งํํ๋ฉด ์ ๋ฐ์ดํธ ๋ฉ๋๋ค.
ํฑํํ ๊ฒ์์ ์ต์ํด์ก๋ค๋ฉด ์ข ๋ฃํด๋ ๊ด์ฐฎ์ต๋๋ค. ์ฐ๋ฆฌ๋ ์์ต์์ ๊ฐ๋จํ ํ ํ๋ฆฟ์์ ์์ํ ๊ฒ์ ๋๋ค. ๋ค์ ๋จ๊ณ์์๋ ๊ฒ์ ๊ตฌํ์ ์์ํ๊ธฐ ์ํ ์ค์ ์ ๋ค๋ฃน๋๋ค.
ํ์ํ ์ ์ ์ง์
HTML๊ณผ JavaScript์ ์ด๋ ์ ๋ ์ต์ํ๋ค๊ณ ๊ฐ์ ํ์ง๋ง ๋ค๋ฅธ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด๋ฅผ ์ฌ์ฉํ๋๋ผ๋ ์์ต์๋ฅผ ๋ฐ๋ผ๊ฐ ์ ์์ต๋๋ค. ๋ํ ํจ์, ๊ฐ์ฒด, ๋ฐฐ์ด, ๊ฐ๋ฅํ๋ค๋ฉด ํด๋์ค ๊ฐ์ ํ๋ก๊ทธ๋๋ฐ ๊ฐ๋ ์ ์ต์ํ๋ค๊ณ ๊ฐ์ ํฉ๋๋ค.
JavaScript๋ฅผ ๋ค์ ๋ณด๊ณ ์ถ๋ค๋ฉด ์ด ๊ฐ์ด๋๋ฅผ ์ถ์ฒํฉ๋๋ค. JavaScript์ ์ต์ ๋ฒ์ ์ธ ES6์ ๋ช ๊ฐ์ง ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ค๋ ์ฌ์ค์ ์ฃผ๋ชฉํด์ฃผ์ธ์. ์์ต์์์๋ ํ์ดํ ํจ์, ํด๋์ค, let
, const
๋ฅผ ์ฌ์ฉํฉ๋๋ค. Babel REPL์ ์ฌ์ฉํ์ฌ ES6 ์ฝ๋๊ฐ ์ด๋ป๊ฒ ์ปดํ์ผ๋๋์ง ํ์ธํ ์ ์์ต๋๋ค.
์์ต์ ํ๊ฒฝ์ค์
์์ต์๋ฅผ ์์ฑํ๋ ๋ฐฉ๋ฒ์๋ ๋ ๊ฐ์ง๊ฐ ์์ต๋๋ค. ๋ธ๋ผ์ฐ์ ์์ ์ฝ๋๋ฅผ ์์ฑํด๋ ๋๊ณ ์ปดํจํฐ์ ๋ก์ปฌ ๊ฐ๋ฐ ํ๊ฒฝ์ ์ค์ ํด๋ ๋ฉ๋๋ค.
์ ํ 1: ๋ธ๋ผ์ฐ์ ์ ์ฝ๋ ์์ฑํ๊ธฐ
์ด ์ต์ ์ ๊ฐ์ฅ ๋น ๋ฅด๊ฒ ์์ํ๋ ๋ฐฉ์์ ๋๋ค!
๋จผ์ ์ ํญ์์ ์ด๊ธฐ ์ฝ๋๋ฅผ ์ด์ด์ฃผ์ธ์. ์ ํญ์ ๋น์ด์๋ ํฑํํ ๊ฒ์ํ๊ณผ React ์ฝ๋๋ฅผ ๋ณด์ฌ์ค ๊ฒ์ ๋๋ค. ์ฐ๋ฆฌ๋ ์์ต์์์ React ์ฝ๋๋ฅผ ํธ์งํ ๊ฒ์ ๋๋ค.
์ด์ ๋ ๋ฒ์งธ ์ค์ ์ต์ ์ ๊ฑด๋๋ฐ๊ณ ๊ฐ์ ๋จ๋ฝ์ผ๋ก ๋์ด๊ฐ์ React์ ๋ํ ๊ฐ์๋ฅผ ํ์ธํด์ฃผ์ธ์.
์ ํ 2: ์์ ์ ์ปดํจํฐ์์ ์ฝ๋ ์์ฑํ๊ธฐ
์ด ๋ฐฉ์์ ์์ ํ ์ ํ์ฌํญ์ด๋ฉฐ ์ด ์์ต์์ ํ์ํ ๊ฒ์ ์๋๋๋ค!
์ ํ ์ฌํญ: ์ ํธํ๋ ํ ์คํธ ํธ์ง๊ธฐ๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํ ์ง์นจ
์ด ์ค์ ์์๋ ๋ ๋ง์ ์์ ์ด ํ์ํ์ง๋ง, ์ ํธํ๋ ํธ์ง๊ธฐ๋ฅผ ์ฌ์ฉํ์ฌ ์์ต์๋ฅผ ์์ฑํ ์ ์์ต๋๋ค. ์๋์ ๋จ๊ณ๋ฅผ ๋ฐ๋ผ์ฃผ์ธ์.
- ์ต์ ๋ฒ์ ์ Node.js๊ฐ ์ค์น๋์ด ์๋์ง ํ์ธํด์ฃผ์ธ์.
- Create React App ์ค์น ์ง์นจ์ ๋ฐ๋ผ ์๋ก์ด ํ๋ก์ ํธ๋ฅผ ์์ฑํด์ฃผ์ธ์.
npx create-react-app my-app
- ์๋ก์ด ํ๋ก์ ํธ์
src/
ํด๋์ ์๋ ๋ชจ๋ ํ์ผ์ ์ญ์ ํด ์ฃผ์ธ์.
์ฃผ์
src
ํด๋ ์ ์ฒด๊ฐ ์๋๋ผ ํด๋ ๋ด๋ถ์ ๊ธฐ์กด ์์ค ํ์ผ๋ค๋ง ์ญ์ ํด ์ฃผ์ธ์. ๋ค์ ๋จ๊ณ์์ ๊ธฐ๋ณธ ์์ค ํ์ผ์ ์ด ํ๋ก์ ํธ์ ์์๋ก ๋ฐ๊ฟ ๊ฒ์ ๋๋ค.
cd my-app
cd src
# Mac ๋๋ Linux ์ฌ์ฉ์์ ๊ฒฝ์ฐ
rm -f *
# Windows ์ฌ์ฉ์
del *
# ๋ค์ ํ๋ก์ ํธ ํด๋๋ก ๋์๊ฐ์ธ์.
cd ..
src/
ํด๋์index.css
๋ผ๋ ํ์ผ์ ์์ฑํ๊ณ ์ด CSS ์ฝ๋๋ฅผ ์ถ๊ฐํด์ฃผ์ธ์.src/
ํด๋์index.js
๋ผ๋ ํ์ผ์ ์์ฑํ๊ณ ์ด JS ์ฝ๋๋ฅผ ์ถ๊ฐํด์ฃผ์ธ์.- ์์์ ์์ฑํ
index.js
์ ์๋จ์ ์๋ ์ธ ์ค์ ์ถ๊ฐํด์ฃผ์ธ์.
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
์ด์ ํ๋ก์ ํธ ํด๋์์ npm start
๋ช
๋ น์ด๋ฅผ ์คํํ๊ณ ๋ธ๋ผ์ฐ์ ์์ http://localhost:3000
๋ฅผ ์ด๋ฉด ๋น์ด์๋ ํฑํํ ํ๋๋ฅผ ํ์ธํ ์ ์์ต๋๋ค.
์๋ํฐ์์ ๊ตฌ๋ฌธ ๊ฐ์กฐ ํ์๋ฅผ ์ค์ ํ๊ธฐ ์ํด ์ด ์ง์นจ์ ๋ฐ๋ฅด๊ธธ ๊ถ์ฅํฉ๋๋ค.
๋์์ด ํ์ํ ๋!
๋งํ๋ ๋ถ๋ถ์ด ์๊ฒผ๋ค๋ฉด ์ปค๋ฎค๋ํฐ์์ ์ง์ํ๋ ์๋ฃ๋ฅผ ํ์ธํด๋ณด์ธ์. ํนํ Reactiflux Chat์ ๋น ๋ฅด๊ฒ ๋์์ ๋ฐ์ ์ ์๋ ์ข์ ๋ฐฉ๋ฒ์ ๋๋ค. ์ํ๋ ๋ต์ ์ป์ง ๋ชปํ๊ฑฐ๋ ๊ณ์ ๋งํ ์ํ๋ผ๋ฉด ์ด์๋ฅผ ์ ์ถํด์ฃผ์ธ์. ์ฐ๋ฆฌ๊ฐ ๋์๋๋ฆฌ๊ฒ ์ต๋๋ค.
๊ฐ์
์ด์ ์ค์ ์ ์๋ฃํ์ผ๋ React์ ๊ฐ์๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค!
React๋ ๋ฌด์์ธ๊ฐ์?
React๋ ์ฌ์ฉ์ ์ธํฐํ์ด์ค๋ฅผ ๊ตฌ์ถํ๊ธฐ ์ํ ์ ์ธ์ ์ด๊ณ ํจ์จ์ ์ด๋ฉฐ ์ ์ฐํ JavaScript ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋๋ค. โ์ปดํฌ๋ํธโ๋ผ๊ณ ๋ถ๋ฆฌ๋ ์๊ณ ๊ณ ๋ฆฝ๋ ์ฝ๋์ ํํธ์ ์ด์ฉํ์ฌ ๋ณต์กํ UI๋ฅผ ๊ตฌ์ฑํ๋๋ก ๋์ต๋๋ค.
React๋ ๋ช ๊ฐ์ง ์ข
๋ฅ์ ์ปดํฌ๋ํธ๋ฅผ ๊ฐ์ง์ง๋ง ์ฐ๋ฆฌ๋ React.Component
์ ํ์ ํด๋์ค๋ฅผ ์ฌ์ฉํด๋ณด๊ฒ ์ต๋๋ค.
class ShoppingList extends React.Component {
render() {
return (
<div className="shopping-list">
<h1>Shopping List for {this.props.name}</h1>
<ul>
<li>Instagram</li>
<li>WhatsApp</li>
<li>Oculus</li>
</ul>
</div>
);
}
}
// ์ฌ์ฉ ์์ : <ShoppingList name="Mark" />
XML๊ณผ ์ ์ฌํ ์ฌ๋ฐ๋ ํ๊ทธ๋ฅผ ์ฌ์ฉํ ๊ฒ์ ๋๋ค. ์ฐ๋ฆฌ๋ ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ์ฌ React์๊ฒ ํ๋ฉด์ ํํํ๊ณ ์ถ์ ๊ฒ์ด ๋ฌด์์ธ์ง ์๋ ค์ค๋๋ค. ๋ฐ์ดํฐ๊ฐ ๋ณ๊ฒฝ๋ ๋ React๋ ์ปดํฌ๋ํธ๋ฅผ ํจ์จ์ ์ผ๋ก ์ ๋ฐ์ดํธํ๊ณ ๋ค์ ๋ ๋๋งํฉ๋๋ค.
์ฌ๊ธฐ์์ ShoppingList๋ React ์ปดํฌ๋ํธ ํด๋์ค ๋๋ React ์ปดํฌ๋ํธ ํ์
์
๋๋ค. ๊ฐ๋ณ ์ปดํฌ๋ํธ๋ props
๋ผ๋ ๋งค๊ฐ๋ณ์๋ฅผ ๋ฐ์์ค๊ณ render
ํจ์๋ฅผ ํตํด ํ์ํ ๋ทฐ ๊ณ์ธต ๊ตฌ์กฐ๋ฅผ ๋ฐํํฉ๋๋ค.
render
ํจ์๋ ํ๋ฉด์์ ๋ณด๊ณ ์ ํ๋ ๋ด์ฉ์ ๋ฐํํฉ๋๋ค. React๋ ์ค๋ช
์ ์ ๋ฌ๋ฐ๊ณ ๊ฒฐ๊ณผ๋ฅผ ํ์ํฉ๋๋ค. ํนํ render
๋ ๋ ๋๋งํ ๋ด์ฉ์ ๊ฒฝ๋ํํ React ์๋ฆฌ๋จผํธ๋ฅผ ๋ฐํํฉ๋๋ค. ๋ค์์ React ๊ฐ๋ฐ์๋ โJSXโ๋ผ๋ ํน์ํ ๋ฌธ๋ฒ์ ์ฌ์ฉํ์ฌ React์ ๊ตฌ์กฐ๋ฅผ ๋ณด๋ค ์ฝ๊ฒ ์์ฑํฉ๋๋ค. <div />
๊ตฌ๋ฌธ์ ๋น๋ํ๋ ์์ ์์ React.createElement('div')
๋ก ๋ณํ๋ฉ๋๋ค. ์์์ ๋ณธ ์์๋ ์๋์ ๊ฐ์ด ๋ณํํฉ๋๋ค.
return React.createElement('div', {className: 'shopping-list'},
React.createElement('h1', /* ... h1 children ... */),
React.createElement('ul', /* ... ul children ... */)
);
์ ์ฒด ์ฝ๋๋ ์ฌ๊ธฐ์ ํ์ธํด์ฃผ์ธ์.
createElement()
์ ๋ํด ๊ถ๊ธํ ์ ์ด ์๋ค๋ฉด API ์ฐธ์กฐ์์ ์์ธํ ์ค๋ช
์ ํ์ธํ ์ ์์ต๋๋ค. ํ์ง๋ง ์์ต์์์๋ ์ด ๋ฐฉ์์ด ์๋๋ผ JSX๋ฅผ ๊ณ์ ์ฌ์ฉํ ๊ฒ์
๋๋ค.
JSX๋ JavaScript์ ๊ฐ๋ ฅํ ๊ธฐ๋ฅ์ ๊ฐ์ง๊ณ ์์ต๋๋ค. JSX ๋ด๋ถ์ ์ค๊ดํธ ์์ ์ด๋ค JavaScript ํํ์๋ ์ฌ์ฉํ ์ ์์ต๋๋ค. React ์๋ฆฌ๋จผํธ๋ JavaScript ๊ฐ์ฒด์ด๋ฉฐ ๋ณ์์ ์ ์ฅํ๊ฑฐ๋ ํ๋ก๊ทธ๋จ ์ฌ๊ธฐ์ ๊ธฐ์ ์ ๋ฌํ ์ ์์ต๋๋ค.
ShoppingList
์ปดํฌ๋ํธ๋ <div />
์ <li />
๊ฐ์ ๋ด๊ฐ DOM ์ปดํฌ๋ํธ๋ง์ ๋ ๋๋งํ์ง๋ง ์ปดํฌ๋ํธ๋ฅผ ์กฐํฉํ์ฌ ์ปค์คํ
React ์ปดํฌ๋ํธ๋ฅผ ๋ ๋๋งํ๋ ๊ฒ๋ ๊ฐ๋ฅํฉ๋๋ค. ์๋ฅผ ๋ค์ด <ShoppingList />
๋ฅผ ์์ฑํ์ฌ ๋ชจ๋ ์ผํ ๋ชฉ๋ก์ ์ฐธ์กฐํ ์ ์์ต๋๋ค. React ์ปดํฌ๋ํธ๋ ์บก์ํ๋์ด ๋
๋ฆฝ์ ์ผ๋ก ๋์ํ ์ ์์ต๋๋ค. ์ด๋ฌํ ์ด์ ๋ก ๋จ์ํ ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ์ฌ ๋ณต์กํ UI๋ฅผ ๊ตฌํํ ์ ์์ต๋๋ค.
์ด๊ธฐ ์ฝ๋ ์ดํด๋ณด๊ธฐ
๋ธ๋ผ์ฐ์ ์์ ์์ต์ ์์ฑ์ ํ๋ ๊ฒฝ์ฐ ์ ํญ์์ ์ด๊ธฐ ์ฝ๋๋ฅผ ์ด์ด์ฃผ์ธ์. ๋ก์ปฌ ํ๊ฒฝ์์ ์งํํ๋ ๊ฒฝ์ฐ ํ๋ก์ ํธ ํด๋์์ src/index.js
๋ฅผ ์ด์ด์ฃผ์ธ์(์ด ํ์ผ์ ์ค์ ์์ ๋ค๋ฃฌ ์ ์ด ์์ต๋๋ค).
์ด๊ธฐ ์ฝ๋๋ ์ ์ํ ํฑํํ ์ ๊ธฐ๋ณธ ํ์ ๋๋ค. CSS ์คํ์ผ์ ์ ๊ณต๋๊ธฐ ๋๋ฌธ์ React๋ฅผ ๋ฐฐ์ฐ๋ ๊ฒ๊ณผ ๊ฒ์์ ํ๋ก๊ทธ๋๋ฐํ๋ ๋ฐ์๋ง ์ง์คํ๋ฉด ๋ฉ๋๋ค.
์ฝ๋๋ฅผ ์ดํด๋ณด๋ฉด ์ธ ๊ฐ์ง React ์ปดํฌ๋ํธ๋ฅผ ํ์ธํ ์ ์์ต๋๋ค.
- Square
- Board
- Game
Square ์ปดํฌ๋ํธ๋ <button>
์ ๋ ๋๋งํ๊ณ Board๋ ์ฌ๊ฐํ 9๊ฐ๋ฅผ ๋ ๋๋งํฉ๋๋ค. Game ์ปดํฌ๋ํธ๋ ๊ฒ์ํ์ ๋ ๋๋งํ๋ฉฐ ๋์ค์ ์์ ํ ์๋ฆฌ ํ์์ ๊ฐ์ ๊ฐ์ง๊ณ ์์ต๋๋ค. ์ง๊ธ์ ์ฌ์ฉ์์ ์ํธ์์ฉํ๋ ์ปดํฌ๋ํธ๊ฐ ์์ต๋๋ค.
Props๋ฅผ ํตํด ๋ฐ์ดํฐ ์ ๋ฌํ๊ธฐ
๋ณธ๊ฒฉ์ ์ผ๋ก ์์ํ๊ธฐ ์ํด Board ์ปดํฌ๋ํธ์์ Square ์ปดํฌ๋ํธ๋ก ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํด ๋ด ์๋ค.
์์ต์๋ฅผ ๋ฐ๋ฅผ ๋ ๋ณต์ฌ/๋ถ์ฌ๋ฃ๊ธฐ๊ฐ ์๋๋ผ ์์ผ๋ก ์ง์ ์ฝ๋๋ฅผ ์์ฑํ๊ธธ ์ถ์ฒํฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ์ฝ๋๋ฅผ ๋ชธ์ผ๋ก ๊ธฐ์ตํ๊ณ ์ดํด๋ ฅ์ ๋ ๋์ผ ์ ์์ต๋๋ค.
Square์ value
prop์ ์ ๋ฌํ๊ธฐ ์ํด Board์ renderSquare
ํจ์ ์ฝ๋๋ฅผ ์์ ํด์ฃผ์ธ์.
class Board extends React.Component {
renderSquare(i) {
return <Square value={i} />; }
}
๊ฐ์ ํ์ํ๊ธฐ ์ํด Square์ render
ํจ์์์ {/* TODO */}
๋ฅผ {this.props.value}
๋ก ์์ ํด์ฃผ์ธ์.
class Square extends React.Component {
render() {
return (
<button className="square">
{this.props.value} </button>
);
}
}
๋ณ๊ฒฝ ์ ์๋
๋ณ๊ฒฝ ํ์๋ ๋ ๋๋ง ๋ ๊ฒฐ๊ณผ์์ ๊ฐ ์ฌ๊ฐํ์ ์ซ์๊ฐ ํ์๋ฉ๋๋ค.
์ง๊ธ๊น์ง์ ์ ์ฒด ์ฝ๋ ํ์ธํ๊ธฐ
์ถํํฉ๋๋ค! ๋ถ๋ชจ Board ์ปดํฌ๋ํธ์์ ์์ Square ์ปดํฌ๋ํธ๋ก โprop์ ์ ๋ฌโํ์ต๋๋ค. props ์ ๋ฌํ๊ธฐ๋ React ์ฑ์์ ๋ถ๋ชจ์์ ์์์ผ๋ก ์ ๋ณด๊ฐ ์ด๋ป๊ฒ ํ๋ฌ๊ฐ๋์ง ์๋ ค์ค๋๋ค.
์ฌ์ฉ์์ ์ํธ์์ฉํ๋ ์ปดํฌ๋ํธ ๋ง๋ค๊ธฐ
Square ์ปดํฌ๋ํธ๋ฅผ ํด๋ฆญํ๋ฉด โXโ๊ฐ ์ฒดํฌ๋๋๋ก ๋ง๋ค์ด๋ด
์๋ค.
๋จผ์ Square ์ปดํฌ๋ํธ์ render()
ํจ์์์ ๋ฐํํ๋ ๋ฒํผ ํ๊ทธ๋ฅผ ์๋์ ๊ฐ์ด ๋ณ๊ฒฝํด์ฃผ์ธ์.
class Square extends React.Component {
render() {
return (
<button className="square" onClick={function() { console.log('click'); }}> {this.props.value}
</button>
);
}
}
Square๋ฅผ ํด๋ฆญํ๋ฉด โclickโ์ด ๋ธ๋ผ์ฐ์ ๊ฐ๋ฐ์ ๋๊ตฌ์ ์ฝ์์ ์ถ๋ ฅ๋๋ ๊ฑธ ํ์ธํ ์ ์์ต๋๋ค.
์ฃผ์
ํ์ดํ ํ์๋ฅผ ์ค์ด๊ณ
this
์ ํผ๋์ค๋ฌ์ด ๋์์ ํผํ๊ธฐ ์ํด ์๋๋ถํฐ๋ ์ด๋ฒคํธ ํธ๋ค๋ฌ์ ํ์ดํ ํจ์๋ฅผ ์ฌ์ฉํ๊ฒ ์ต๋๋ค.class Square extends React.Component { render() { return ( <button className="square" onClick={() => console.log('click')}> {this.props.value} </button> ); } }
onClick={() => console.log('click')}
์ด ์ด๋ป๊ฒ ๋์ํ๋์ง ์ดํด๋ณด๋ฉดonClick
prop์ผ๋ก ํจ์๋ฅผ ์ ๋ฌํ๊ณ ์์ต๋๋ค. React๋ ํด๋ฆญํ์ ๋์๋ง ์ด ํจ์๋ฅผ ํธ์ถํ ๊ฒ์ ๋๋ค.() =>
์ ์์ด๋ฒ๋ฆฌ๊ณonClick={console.log('click')}
์ด๋ผ๊ณ ์์ฑํ๋ ๊ฒ์ ์์ฃผ ๋ฐ์ํ๋ ์ค์์ด๋ฉฐ ์ปดํฌ๋ํธ๊ฐ ๋ค์ ๋ ๋๋งํ ๋๋ง๋ค ๊ฒฝ๊ณ ์ฐฝ์ ๋์ธ ๊ฒ์ ๋๋ค.
๋ค์ ๋จ๊ณ๋ก Square ์ปดํฌ๋ํธ๋ฅผ ํด๋ฆญํ ๊ฒ์ โ๊ธฐ์ตํ๊ฒโ ๋ง๋ค์ด โXโ ํ์๋ฅผ ์ฑ์ ๋ฃ์ผ๋ ค๊ณ ํฉ๋๋ค. ๋ฌด์ธ๊ฐ๋ฅผ โ๊ธฐ์ตํ๊ธฐโ์ํด component๋ state๋ฅผ ์ฌ์ฉํฉ๋๋ค.
React ์ปดํฌ๋ํธ๋ ์์ฑ์์ this.state
๋ฅผ ์ค์ ํ๋ ๊ฒ์ผ๋ก state๋ฅผ ๊ฐ์ง ์ ์์ต๋๋ค. this.state
๋ ์ ์๋ React ์ปดํฌ๋ํธ์ ๋ํด ๋น๊ณต๊ฐ๋ก ๊ฐ์ฃผํด์ผ ํฉ๋๋ค. ์ด์ Square์ ํ์ฌ ๊ฐ์ this.state
์ ์ ์ฅํ๊ณ Square๋ฅผ ํด๋ฆญํ๋ ๊ฒฝ์ฐ ๋ณ๊ฒฝํ๊ฒ ์ต๋๋ค.
์ฐ์ ํด๋์ค์ ์์ฑ์๋ฅผ ์ถ๊ฐํ์ฌ state๋ฅผ ์ด๊ธฐํํฉ๋๋ค.
class Square extends React.Component {
constructor(props) { super(props); this.state = { value: null, }; }
render() {
return (
<button className="square" onClick={() => console.log('click')}>
{this.props.value}
</button>
);
}
}
์ฃผ์
JavaScript ํด๋์ค์์ ํ์ ํด๋์ค์ ์์ฑ์๋ฅผ ์ ์ํ ๋ ํญ์
super
๋ฅผ ํธ์ถํด์ผํฉ๋๋ค. ๋ชจ๋ React ์ปดํฌ๋ํธ ํด๋์ค๋์์ฑ์
๋ฅผ ๊ฐ์ง ๋super(props)
ํธ์ถ ๊ตฌ๋ฌธ๋ถํฐ ์์ฑํด์ผ ํฉ๋๋ค.
์ด์ Square๋ฅผ ํด๋ฆญํ ๋ ํ์ฌ state ๊ฐ์ ํ์ํ๊ธฐ ์ํด render
ํจ์๋ฅผ ๋ณ๊ฒฝํ ๊ฒ์
๋๋ค.
<button>
ํ๊ทธ ์this.props.value
๋ฅผthis.state.value
๋ก ๋ณ๊ฒฝํด์ฃผ์ธ์.onClick={...}
์ด๋ฒคํธ ํธ๋ค๋ฌ๋ฅผonClick={() => this.setState({value: 'X'})}
๋ก ๋ณ๊ฒฝํด์ฃผ์ธ์.- ๊ฐ๋
์ฑ์ ๋์ด๊ธฐ ์ํด
className
๊ณผonClick
props๋ฅผ ๋ณ๋์ ์ค์ ๋ฃ์ด์ฃผ์ธ์.
์ด์ ๊ฐ์ ๋ณ๊ฒฝ ํ์ Square์ render
ํจ์์์ ๋ฐํํ๋ <button>
ํ๊ทธ๋ ์๋์ ํํ์ ๊ฐ์ต๋๋ค.
class Square extends React.Component {
constructor(props) {
super(props);
this.state = {
value: null,
};
}
render() {
return (
<button
className="square" onClick={() => this.setState({value: 'X'})} >
{this.state.value} </button>
);
}
}
Square์ render
ํจ์ ๋ด๋ถ์์ onClick
ํธ๋ค๋ฌ๋ฅผ ํตํด this.setState
๋ฅผ ํธ์ถํ๋ ๊ฒ์ผ๋ก React์๊ฒ <button>
์ ํด๋ฆญํ ๋ Square๊ฐ ๋ค์ ๋ ๋๋งํด์ผ ํ๋ค๊ณ ์๋ฆด ์ ์์ต๋๋ค. ์
๋ฐ์ดํธ ์ดํ์ Square์ this.state.value
๋ 'X'
๊ฐ ๋์ด ๊ฒ์ ํ์์ X
๊ฐ ๋ํ๋๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค. ์ด๋ค Square๋ฅผ ํด๋ฆญํ๋ X
๊ฐ ๋ํ๋ ๊ฒ์
๋๋ค.
์ปดํฌ๋ํธ์์ setState
๋ฅผ ํธ์ถํ๋ฉด React๋ ์๋์ผ๋ก ์ปดํฌ๋ํธ ๋ด๋ถ์ ์์ ์ปดํฌ๋ํธ ์ญ์ ์
๋ฐ์ดํธํฉ๋๋ค.
์ง๊ธ๊น์ง์ ์ ์ฒด ์ฝ๋ ํ์ธํ๊ธฐ
๊ฐ๋ฐ์ ๋๊ตฌ
Chrome๊ณผ Firefox์ React Devtools ํ์ฅ ํ๋ก๊ทธ๋จ์ ์ฌ์ฉํ๋ฉด ๋ธ๋ผ์ฐ์ ๊ฐ๋ฐ์ ๋๊ตฌ์์ React ์ปดํฌ๋ํธ ํธ๋ฆฌ๋ฅผ ๊ฒ์ฌํ ์ ์์ต๋๋ค.

React DevTools๋ฅผ ํตํด React ์ปดํฌ๋ํธ์ props์ state๋ ํ์ธํ ์ ์์ต๋๋ค.
React DevTools๋ฅผ ์ค์นํ ํ์ ํ์ด์ง์ ๋ชจ๋ ์๋ฆฌ๋จผํธ์ ์ค๋ฅธ์ชฝ ํด๋ฆญ์ ํ๊ณ โ์์ ๊ฒ์ฌโ๋ฅผ ํด๋ฆญํ์ฌ ๊ฐ๋ฐ์ ๋๊ตฌ๋ฅผ ์ด๋ฉด ํญ์ ์ค๋ฅธ์ชฝ ๋์ React ํญ(โโ๏ธ Componentsโ์ โโ๏ธ Profilerโ)์ ํ์ธํ์ค ์ ์์ต๋๋ค. ์ปดํฌ๋ํธ ํธ๋ฆฌ๋ฅผ ๊ฒ์ฌํ๊ณ ์ถ๋ค๋ฉด โโ๏ธ Componentsโ๋ฅผ ์ฌ์ฉํด์ฃผ์ธ์.
๊ทธ๋ฌ๋ CodePen์์ ๋๊ตฌ๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์ ๋ช ๊ฐ์ง ๋จ๊ณ๊ฐ ์ถ๊ฐ๋ก ํ์ํฉ๋๋ค.
- ๋ก๊ทธ์ธํ์ธ์. ๋๋ ๊ฐ์ ํ ์ด๋ฉ์ผ์ ํ์ธํด์ฃผ์ธ์ (์คํธ ๋ฐฉ์ง๋ฅผ ์ํด ํ์).
- โForkโ ๋ฒํผ์ ํด๋ฆญํ์ธ์.
- โChange Viewโ๋ฅผ ํด๋ฆญํ์ฌ โDebug modeโ๋ฅผ ์ ํํด์ฃผ์ธ์.
- ์ ํญ์ด ์ด๋ฆฌ๋ฉด ๊ฐ๋ฐ์ ๋๊ตฌ์์ React ํญ์ ํ์ธํด์ฃผ์ธ์.
๊ฒ์ ์์ฑํ๊ธฐ
์ด์ ํฑํํ ๊ฒ์์ ์ํ ๊ธฐ๋ณธ ๊ตฌ์ฑ ์์๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค. ์์ ํ ๊ฒ์์ ์ํด ๊ฒ์ํ์ โXโ์ โOโ๋ฅผ ๋ฒ๊ฐ์ ํ์ํ ํ์๊ฐ ์์ผ๋ฉฐ ์น์๋ฅผ ๊ฒฐ์ ํ๋ ๋ฐฉ๋ฒ์ด ํ์ํฉ๋๋ค.
State ๋์ด์ฌ๋ฆฌ๊ธฐ
ํ์ฌ ๊ฒ์์ state๋ฅผ ๊ฐ๊ฐ์ Square ์ปดํฌ๋ํธ์์ ์ ์งํ๊ณ ์์ต๋๋ค. ์น์๋ฅผ ํ์ธํ๊ธฐ ์ํด 9๊ฐ ์ฌ๊ฐํ์ ๊ฐ์ ํ ๊ณณ์ ์ ์งํ ๊ฒ์ ๋๋ค.
Board๊ฐ ๊ฐ Square์ Square์ state๋ฅผ ์์ฒญํด์ผ ํ๋ค๊ณ ์๊ฐํ ์๋ ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ React์์ ์ด๋ฐ ์ ๊ทผ์ด ๊ฐ๋ฅํ๊ธฐ๋ ํ์ง๋ง ์ด ๋ฐฉ์์ ์ฝ๋๋ฅผ ์ดํดํ๊ธฐ ์ด๋ ต๊ฒ ๋ง๋ค๊ณ ๋ฒ๊ทธ์ ์ทจ์ฝํ๋ฉฐ ๋ฆฌํฉํ ๋ง์ด ์ด๋ ต๊ธฐ ๋๋ฌธ์ ์ถ์ฒํ์ง ์์ต๋๋ค. ๊ฐ Square๊ฐ ์๋ ๋ถ๋ชจ Board ์ปดํฌ๋ํธ์ ๊ฒ์์ ์ํ๋ฅผ ์ ์ฅํ๋ ๊ฒ์ด ๊ฐ์ฅ ์ข์ ๋ฐฉ๋ฒ์ ๋๋ค. ๊ฐ Square์ ์ซ์๋ฅผ ๋๊ฒจ์ฃผ์์ ๋์ ๊ฐ์ด Board ์ปดํฌ๋ํธ๋ ๊ฐ Square์๊ฒ prop์ ์ ๋ฌํ๋ ๊ฒ์ผ๋ก ๋ฌด์์ ํ์ํ ์ง ์๋ ค์ค๋๋ค.
์ฌ๋ฌ๊ฐ์ ์์์ผ๋ก๋ถํฐ ๋ฐ์ดํฐ๋ฅผ ๋ชจ์ผ๊ฑฐ๋ ๋ ๊ฐ์ ์์ ์ปดํฌ๋ํธ๋ค์ด ์๋ก ํต์ ํ๊ฒ ํ๋ ค๋ฉด ๋ถ๋ชจ ์ปดํฌ๋ํธ์ ๊ณต์ state๋ฅผ ์ ์ํด์ผ ํฉ๋๋ค. ๋ถ๋ชจ ์ปดํฌ๋ํธ๋ props๋ฅผ ์ฌ์ฉํ์ฌ ์์ ์ปดํฌ๋ํธ์ state๋ฅผ ๋ค์ ์ ๋ฌํ ์ ์์ต๋๋ค. ์ด๊ฒ์ ์์ ์ปดํฌ๋ํธ๋ค์ด ์๋ก ๋๋ ๋ถ๋ชจ ์ปดํฌ๋ํธ์ ๋๊ธฐํ ํ๋๋ก ๋ง๋ญ๋๋ค.
state๋ฅผ ๋ถ๋ชจ ์ปดํฌ๋ํธ๋ก ๋์ด์ฌ๋ฆฌ๋ ๊ฒ์ React ์ปดํฌ๋ํธ๋ฅผ ๋ฆฌํฉํ ๋งํ ๋ ํํ ์ฌ์ฉํฉ๋๋ค. ์ด๋ฒ ๊ธฐํ์ ์ํํด ๋ณด๊ฒ ์ต๋๋ค.
Board์ ์์ฑ์๋ฅผ ์ถ๊ฐํ๊ณ 9๊ฐ์ ์ฌ๊ฐํ์ ํด๋นํ๋ 9๊ฐ์ null ๋ฐฐ์ด์ ์ด๊ธฐ state๋ก ์ค์ ํด์ฃผ์ธ์.
class Board extends React.Component {
constructor(props) { super(props); this.state = { squares: Array(9).fill(null), }; }
renderSquare(i) {
return <Square value={i} />;
}
๋์ค์ board๋ฅผ ์ฑ์ฐ๋ฉด this.state.squares
๋ฐฐ์ด์ ์๋์ ๊ฐ์ด ๋ณด์ผ ๊ฒ์
๋๋ค.
[
'O', null, 'X',
'X', 'X', 'O',
'O', null, null,
]
Board์ renderSquare
ํจ์๋ ํ์ฌ ์๋์ ๊ฐ์ ํํ์
๋๋ค.
renderSquare(i) {
return <Square value={i} />;
}
์ฒ์์๋ ๋ชจ๋ Square์์ 0๋ถํฐ 8๊น์ง ์ซ์๋ฅผ ๋ณด์ฌ์ฃผ๊ธฐ ์ํด Board์์ value
prop์ ์์์ผ๋ก ์ ๋ฌํ์ต๋๋ค. ๋ ๋ค๋ฅธ ์ด์ ๋จ๊ณ์์๋ ์ซ์๋ฅผ Square์ ์์ฒด state์ ๋ฐ๋ผ โXโ ํ์๋ก ๋ฐ๊พธ์์ต๋๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ํ์ฌ Square๋ Board์์ ์ ๋ฌํ value
prop์ ๋ฌด์ํ๊ณ ์์ต๋๋ค.
์ด์ prop์ ์ ๋ฌํ๋ ๋ฐฉ๋ฒ์ ๋ค์ ์ฌ์ฉํ ๊ฒ์
๋๋ค. ๊ฐ Square์๊ฒ ํ์ฌ ๊ฐ('X'
, 'O'
, ๋๋ null
)์ ํํํ๋๋ก Board๋ฅผ ์์ ํ ๊ฒ์
๋๋ค. Board์ ์์ฑ์์์ squares
๋ฐฐ์ด์ ์ด๋ฏธ ์ ์ธํ์ผ๋ฉฐ renderSquare
ํจ์๋ฅผ ์๋์ ๊ฐ์ด ์์ ํ ๊ฒ์
๋๋ค.
renderSquare(i) {
return <Square value={this.state.squares[i]} />; }
์ง๊ธ๊น์ง์ ์ ์ฒด ์ฝ๋ ํ์ธํ๊ธฐ
Square๋ ์ด์ ๋น ์ฌ๊ฐํ์ 'X'
, 'O'
, ๋๋ null
์ธ value
prop์ ๋ฐ์ต๋๋ค.
๋ค์์ผ๋ก Square๋ฅผ ํด๋ฆญํ ๋ ๋ฐ์ํ๋ ๋ณํ๊ฐ ํ์ํฉ๋๋ค. Board ์ปดํฌ๋ํธ๋ ์ด๋ค ์ฌ๊ฐํ์ด ์ฑ์์ก๋์ง๋ฅผ ์ฌ๋ถ๋ฅผ ๊ด๋ฆฌํ๋ฏ๋ก Square๊ฐ Board๋ฅผ ๋ณ๊ฒฝํ ๋ฐฉ๋ฒ์ด ํ์ํฉ๋๋ค. ์ปดํฌ๋ํธ๋ ์์ ์ด ์ ์ํ state์๋ง ์ ๊ทผํ ์ ์์ผ๋ฏ๋ก Square์์ Board์ state๋ฅผ ์ง์ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค.
๋์ ์ Board์์ Square๋ก ํจ์๋ฅผ ์ ๋ฌํ๊ณ Square๋ ์ฌ๊ฐํ์ ํด๋ฆญํ ๋ ํจ์๋ฅผ ํธ์ถํ ๊ฒ์
๋๋ค. ์ด์ Board์ renderSquare
ํจ์๋ฅผ ์๋์ ๊ฐ์ด ๋ณ๊ฒฝํด์ฃผ์ธ์.
renderSquare(i) {
return (
<Square
value={this.state.squares[i]}
onClick={() => this.handleClick(i)} />
);
}
์ฃผ์
๋ฐํ๋๋ ์๋ฆฌ๋จผํธ๋ฅผ ์ฌ๋ฌ ์ค๋ก ๋๋์ด ๊ฐ๋ ์ฑ์ ํ๋ณดํ์๊ณ ๊ดํธ๋ฅผ ์ถ๊ฐํ์ฌ JavaScript๊ฐ
return
๋ค์ ์ธ๋ฏธ์ฝ๋ก ์ ์ฝ์ ํ์ง ์์๋ ์ฝ๋๊ฐ ๊นจ์ง์ง ์์ต๋๋ค.
์ด์ Board์์ Square๋ก value
์ onClick
๋ ๊ฐ์ props๋ฅผ ์ ๋ฌํ์์ต๋๋ค. onClick
prop์ Square๋ฅผ ํด๋ฆญํ๋ฉด ํธ์ถ๋๋ ํจ์์
๋๋ค. Square๋ฅผ ์๋์ ๊ฐ์ด ๋ณ๊ฒฝํด์ฃผ์ธ์.
- Square์
render
ํจ์ ๋ด๋ถ์this.state.value
๋ฅผthis.props.value
๋ก ๋ฐ๊พธ์ด์ฃผ์ธ์. - Square์
render
ํจ์ ๋ด๋ถ์this.setState()
๋ฅผthis.props.onClick()
์ผ๋ก ๋ฐ๊พธ์ด์ฃผ์ธ์. - Square๋ ๊ฒ์์ ์ํ๋ฅผ ์ ์งํ ํ์๊ฐ ์๊ธฐ ๋๋ฌธ์
constructor
๋ฅผ ์ง์์ฃผ์ธ์.
์ด๋ ๊ฒ ๋ฐ๊พผ ํ์ Square๋ ์๋์ ๊ฐ์ ๋ชจ์ต์ด ๋ฉ๋๋ค.
class Square extends React.Component { render() { return (
<button
className="square"
onClick={() => this.props.onClick()} >
{this.props.value} </button>
);
}
}
Square๋ฅผ ํด๋ฆญํ๋ฉด Board์์ ๋๊ฒจ๋ฐ์ onClick
ํจ์๊ฐ ํธ์ถ๋ฉ๋๋ค. ์ด ๋ ์ผ์ด๋๋ ์ผ์ ์ ๋ฆฌํด๋ณด๊ฒ ์ต๋๋ค.
- ๋ด์ฅ๋ DOM
<button>
์ปดํฌ๋ํธ์ ์๋onClick
prop์ React์๊ฒ ํด๋ฆญ ์ด๋ฒคํธ ๋ฆฌ์ค๋๋ฅผ ์ค์ ํ๋ผ๊ณ ์๋ ค์ค๋๋ค. - ๋ฒํผ์ ํด๋ฆญํ๋ฉด React๋ Square์
render()
ํจ์์ ์ ์๋onClick
์ด๋ฒคํธ ํธ๋ค๋ฌ๋ฅผ ํธ์ถํฉ๋๋ค. - ์ด๋ฒคํธ ํธ๋ค๋ฌ๋
this.props.onClick()
๋ฅผ ํธ์ถํฉ๋๋ค. Square์onClick
prop์ Board์์ ์ ์๋์์ต๋๋ค. - Board์์ Square๋ก
onClick={() => this.handleClick(i)}
๋ฅผ ์ ๋ฌํ๊ธฐ ๋๋ฌธ์ Square๋ฅผ ํด๋ฆญํ๋ฉด Board์handleClick(i)
๋ฅผ ํธ์ถํฉ๋๋ค. - ์์ง
handleClick()
๋ฅผ ์ ์ํ์ง ์์๊ธฐ ๋๋ฌธ์ ์ฝ๋๊ฐ ๊นจ์ง ๊ฒ์ ๋๋ค. ์ง๊ธ์ ์ฌ๊ฐํ์ ํด๋ฆญํ๋ฉด โthis.handleClick is not a functionโ๊ณผ ๊ฐ์ ๋ด์ฉ์ ํ์ํ๋ ๋ถ์ ์๋ฌ ํ๋ฉด์ ๋ณด๊ฒ๋ฉ๋๋ค.
์ฃผ์
DOM
<button>
์๋ฆฌ๋จผํธ์onClick
์ดํธ๋ฆฌ๋ทฐํธ๋ ๋ด์ฅ๋ ์ปดํฌ๋ํธ๋ผ๋ ์ ์์ React์๊ฒ ํน๋ณํ ์๋ฏธ๊ฐ ์์ต๋๋ค. Square๊ฐ์ ์ฌ์ฉ์ ์ ์ ์ปดํฌ๋ํธ์ ๊ฒฝ์ฐ ์ด๋ฆ ์ง์ ์ ์์ ๋กญ์ต๋๋ค. Square์onClick
prop์ด๋ Board์handleClick
ํจ์์๋ ์ด๋ค ์ด๋ฆ๋ ๋ถ์ผ ์ ์์ผ๋ฉฐ ์ฝ๋๋ ๋์ผํ๊ฒ ์๋ํฉ๋๋ค. React์์ ์ด๋ฒคํธ๋ฅผ ๋ํ๋ด๋ prop์๋on[Event]
, ์ด๋ฒคํธ๋ฅผ ์ฒ๋ฆฌํ๋ ํจ์์๋handle[Event]
๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ์ผ๋ฐ์ ์ ๋๋ค.
handleClick
์ ์์ง ์ ์ํ์ง ์์๊ธฐ ๋๋ฌธ์ Square๋ฅผ ํด๋ฆญํ๋ ค๊ณ ํ ๋ ์๋ฌ๊ฐ ๋ฐ์ํฉ๋๋ค. ์ด์ Board ํด๋์ค์ handleClick
์ ์ถ๊ฐํ๊ฒ ์ต๋๋ค.
class Board extends React.Component {
constructor(props) {
super(props);
this.state = {
squares: Array(9).fill(null),
};
}
handleClick(i) { const squares = this.state.squares.slice(); squares[i] = 'X'; this.setState({squares: squares}); }
renderSquare(i) {
return (
<Square
value={this.state.squares[i]}
onClick={() => this.handleClick(i)}
/>
);
}
render() {
const status = 'Next player: X';
return (
<div>
<div className="status">{status}</div>
<div className="board-row">
{this.renderSquare(0)}
{this.renderSquare(1)}
{this.renderSquare(2)}
</div>
<div className="board-row">
{this.renderSquare(3)}
{this.renderSquare(4)}
{this.renderSquare(5)}
</div>
<div className="board-row">
{this.renderSquare(6)}
{this.renderSquare(7)}
{this.renderSquare(8)}
</div>
</div>
);
}
}
์ง๊ธ๊น์ง์ ์ ์ฒด ์ฝ๋ ํ์ธํ๊ธฐ
์ด์ ์ด์ ๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก Square๋ฅผ ํด๋ฆญํ์ฌ ์ฌ๊ฐํ์ ์ฑ์ธ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ด์ ๋ state๊ฐ ๊ฐ Square ์ปดํฌ๋ํธ ๋์ ์ Board ์ปดํฌ๋ํธ์ ์ ์ฅ๋ฉ๋๋ค. Board์ ์ํ๊ฐ ๋ณํํ ๋ Square ์ปดํฌ๋ํธ๋ ์๋์ผ๋ก ๋ค์ ๋ ๋๋งํฉ๋๋ค. Board ์ปดํฌ๋ํธ์ ๋ชจ๋ ์ฌ๊ฐํ์ ์ํ๋ฅผ ์ ์งํ๋ ๊ฒ์ผ๋ก ์ดํ์ ์น์๋ฅผ ๊ฒฐ์ ํ๋ ๊ฒ์ด ๊ฐ๋ฅํฉ๋๋ค.
Square ์ปดํฌ๋ํธ๊ฐ ๋ ์ด์ state๋ฅผ ์ ์งํ์ง ์๊ธฐ ๋๋ฌธ์ Square ์ปดํฌ๋ํธ๋ Board ์ปดํฌ๋ํธ์์ ๊ฐ์ ๋ฐ์ ํด๋ฆญ๋ ๋ Board ์ปดํฌ๋ํธ๋ก ์ ๋ณด๋ฅผ ์ ๋ฌํฉ๋๋ค. React ์ฉ์ด๋ก Square ์ปดํฌ๋ํธ๋ ์ด์ ์ ์ด๋๋ ์ปดํฌ๋ํธ์ ๋๋ค. Board๋ ์ด๋ค์ ์์ ํ ์ ์ดํฉ๋๋ค.
handleClick
์์๋ .slice()
๋ฅผ ํธ์ถํ๋ ๊ฒ์ผ๋ก ๊ธฐ์กด ๋ฐฐ์ด์ ์์ ํ์ง ์๊ณ squares
๋ฐฐ์ด์ ๋ณต์ฌ๋ณธ์ ์์ฑํ์ฌ ์์ ํ๋ ๊ฒ์ ์ฃผ์ํด์ฃผ์ธ์. ์ squares
๋ฐฐ์ด์ ์ฌ๋ณธ์ ์์ฑํ์๋์ง ๋ค์ ๋จ๋ฝ์์ ์ค๋ช
ํ๊ฒ ์ต๋๋ค.
๋ถ๋ณ์ฑ์ด ์ ์ค์ํ ๊น์?
์ด์ ์ฝ๋ ์์์์ ๊ธฐ์กด ๋ฐฐ์ด์ ์์ ํ๋ ๊ฒ์ด ์๋๋ผ .slice()
์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ์ฌ squares
๋ฐฐ์ด์ ์ฌ๋ณธ ๋ง๋ค๊ธฐ๋ฅผ ์ถ์ฒํ์ต๋๋ค. ์ง๊ธ๋ถํฐ ๋ถ๋ณ์ฑ์ด ๋ฌด์์ธ์ง์ ์ ๋ถ๋ณ์ฑ์ด ์ค์ํ์ง ์์๋ณด๊ฒ ์ต๋๋ค.
์ผ๋ฐ์ ์ผ๋ก ๋ฐ์ดํฐ ๋ณ๊ฒฝ์๋ ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ด ์์ต๋๋ค. ์ฒซ ๋ฒ์งธ๋ ๋ฐ์ดํฐ์ ๊ฐ์ ์ง์ ๋ณ๊ฒฝํ๋ ๊ฒ์ ๋๋ค. ๋ ๋ฒ์งธ๋ ์ํ๋ ๋ณ๊ฒฝ ๊ฐ์ ๊ฐ์ง ์๋ก์ด ์ฌ๋ณธ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๊ต์ฒดํ๋ ๊ฒ์ ๋๋ค.
๊ฐ์ฒด ๋ณ๊ฒฝ์ ํตํด ๋ฐ์ดํฐ ์์ ํ๊ธฐ
var player = {score: 1, name: 'Jeff'};
player.score = 2;
// ์ด์ player๋ {score: 2, name: 'Jeff'}์
๋๋ค.
๊ฐ์ฒด ๋ณ๊ฒฝ ์์ด ๋ฐ์ดํฐ ์์ ํ๊ธฐ
var player = {score: 1, name: 'Jeff'};
var newPlayer = Object.assign({}, player, {score: 2});
// ์ด์ player๋ ๋ณํ์ง ์์์ง๋ง newPlayer๋ {score: 2, name: 'Jeff'}์
๋๋ค.
// ๊ฐ์ฒด spread ๊ตฌ๋ฌธ์ ์ฌ์ฉํ๋ค๋ฉด ์ด๋ ๊ฒ ์ธ ์ ์์ต๋๋ค.
// var newPlayer = {...player, score: 2};
์ต์ข ๊ฒฐ๊ณผ๋ ๋์ผํ์ง๋ง ์ง์ ์ ์ธ ๊ฐ์ฒด ๋ณ๊ฒฝ์ด๋ ๊ธฐ๋ณธ ๋ฐ์ดํฐ์ ๋ณ๊ฒฝ์ ํ์ง ์๋๋ค๋ฉด ์๋์ ๊ธฐ์ ๋ ๋ช ๊ฐ์ง ์ด์ ์ ์ป์ ์ ์์ต๋๋ค.
๋ณต์กํ ํน์ง๋ค์ ๋จ์ํ๊ฒ ๋ง๋ฆ
๋ถ๋ณ์ฑ์ ๋ณต์กํ ํน์ง๋ค์ ๊ตฌํํ๊ธฐ ์ฝ๊ฒ ๋ง๋ญ๋๋ค. ์์ต์์์๋ โ์๊ฐ ์ฌํโ ๊ธฐ๋ฅ์ ๊ตฌํํ์ฌ ํฑํํ ๊ฒ์์ ์ด๋ ฅ์ ํ์ธํ๊ณ ์ด์ ๋์์ผ๋ก โ๋๋์๊ฐ ์ ์์ต๋๋คโ. ์ด ๊ธฐ๋ฅ์ ๊ฒ์์๋ง ๊ตญํ๋์ง ์์ต๋๋ค. ํน์ ํ๋์ ์ทจ์ํ๊ณ ๋ค์ ์คํํ๋ ๊ธฐ๋ฅ์ ์ ํ๋ฆฌ์ผ์ด์ ์์ ์ผ๋ฐ์ ์ธ ์๊ตฌ์ฌํญ ์ ๋๋ค. ์ง์ ์ ์ธ ๋ฐ์ดํฐ ๋ณ์ด๋ฅผ ํผํ๋ ๊ฒ์ ์ด์ ๋ฒ์ ์ ๊ฒ์ ์ด๋ ฅ์ ์ ์งํ๊ณ ๋์ค์ ์ฌ์ฌ์ฉํ ์ ์๊ฒ ๋ง๋ญ๋๋ค.
๋ณํ๋ฅผ ๊ฐ์งํจ
๊ฐ์ฒด๊ฐ ์ง์ ์ ์ผ๋ก ์์ ๋๊ธฐ ๋๋ฌธ์ ๋ณต์ ๊ฐ ๊ฐ๋ฅํ ๊ฐ์ฒด์์ ๋ณํ๋ฅผ ๊ฐ์งํ๋ ๊ฒ์ ์ด๋ ต์ต๋๋ค. ๊ฐ์ง๋ ๋ณต์ ๊ฐ ๊ฐ๋ฅํ ๊ฐ์ฒด๋ฅผ ์ด์ ์ฌ๋ณธ๊ณผ ๋น๊ตํ๊ณ ์ ์ฒด ๊ฐ์ฒด ํธ๋ฆฌ๋ฅผ ๋์์ผ ํฉ๋๋ค.
๋ถ๋ณ ๊ฐ์ฒด์์ ๋ณํ๋ฅผ ๊ฐ์งํ๋ ๊ฒ์ ์๋นํ ์ฝ์ต๋๋ค. ์ฐธ์กฐํ๊ณ ์๋ ๋ถ๋ณ ๊ฐ์ฒด๊ฐ ์ด์ ๊ฐ์ฒด์ ๋ค๋ฅด๋ค๋ฉด ๊ฐ์ฒด๋ ๋ณํ ๊ฒ์ ๋๋ค.
React์์ ๋ค์ ๋ ๋๋งํ๋ ์๊ธฐ๋ฅผ ๊ฒฐ์ ํจ
๋ถ๋ณ์ฑ์ ๊ฐ์ฅ ํฐ ์ฅ์ ์ React์์ ์์ ์ปดํฌ๋ํธ๋ฅผ ๋ง๋๋ ๋ฐ ๋์์ ์ค๋ค๋ ๊ฒ์ ๋๋ค. ๋ณํ์ง ์๋ ๋ฐ์ดํฐ๋ ๋ณ๊ฒฝ์ด ์ด๋ฃจ์ด์ก๋์ง ์ฝ๊ฒ ํ๋จํ ์ ์์ผ๋ฉฐ ์ด๋ฅผ ๋ฐํ์ผ๋ก ์ปดํฌ๋ํธ๊ฐ ๋ค์ ๋ ๋๋งํ ์ง๋ฅผ ๊ฒฐ์ ํ ์ ์์ต๋๋ค.
shouldComponentUpdate()
์ ์์ ์ปดํฌ๋ํธ๋ฅผ ์์ฑํ๋ ๋ฒ์ ๋ํด ๋ ์์๋ณด๊ณ ์ถ๋ค๋ฉด ์ฑ๋ฅ ์ต์ ํํ๊ธฐ๋ฅผ ๋ณด์ธ์.
ํจ์ ์ปดํฌ๋ํธ
์ด์ Square๋ฅผ ํจ์ ์ปดํฌ๋ํธ๋ก ๋ฐ๊ฟ๋ณด๊ฒ ์ต๋๋ค.
React์์ ํจ์ ์ปดํฌ๋ํธ๋ ๋ ๊ฐ๋จํ๊ฒ ์ปดํฌ๋ํธ๋ฅผ ์์ฑํ๋ ๋ฐฉ๋ฒ์ด๋ฉฐ state ์์ด render
ํจ์๋ง์ ๊ฐ์ง๋๋ค. React.Component
๋ฅผ ํ์ฅํ๋ ํด๋์ค๋ฅผ ์ ์ํ๋ ๋์ props
๋ฅผ ์
๋ ฅ๋ฐ์์ ๋ ๋๋งํ ๋์์ ๋ฐํํ๋ ํจ์๋ฅผ ์์ฑํ ์ ์์ต๋๋ค. ํจ์ ์ปดํฌ๋ํธ๋ ํด๋์ค๋ก ์์ฑํ๋ ๊ฒ๋ณด๋ค ๋น ๋ฅด๊ฒ ์์ฑํ ์ ์์ผ๋ฉฐ ๋ง์ ์ปดํฌ๋ํธ๋ฅผ ํจ์ ์ปดํฌ๋ํธ๋ก ํํํ ์ ์์ต๋๋ค.
Square ํด๋์ค๋ฅผ ์๋์ ํจ์๋ก ๋ฐ๊ฟ๋ณด์ธ์.
function Square(props) {
return (
<button className="square" onClick={props.onClick}>
{props.value}
</button>
);
}
๋ชจ๋ this.props
๋ฅผ props
๋ก ๋ณ๊ฒฝํ์์ต๋๋ค.
์ง๊ธ๊น์ง์ ์ ์ฒด ์ฝ๋ ํ์ธํ๊ธฐ
์ฃผ์
Square๋ฅผ ํจ์ ์ปดํฌ๋ํธ๋ก ์์ ํ์ ๋
onClick={() => this.props.onClick()}
์onClick={props.onClick}
๋ก ๊ฐ๊ฒฐํ๊ฒ ์์ฑํ์ต๋๋ค. ์์ชฝ ๋ชจ๋ ๊ดํธ๊ฐ ์ฌ๋ผ์ง ๊ฒ์ ์ฃผ๋ชฉํด์ฃผ์ธ์.
์์ ๋ง๋ค๊ธฐ
์ฐ๋ฆฌ์ ํฑํํ ๊ฒ์์ด ๊ฐ์ง ํฐ ๋ฌธ์ ์ ์ ๊ณ ์น ์๊ฐ์ ๋๋ค. ๊ฒ์ํ์์ โOโ๊ฐ ํ์๋์ง ์๋ ์ ์ด์ฃ .
์ฒซ ๋ฒ์งธ ์ฐจ๋ก๋ฅผ โXโ๋ก ์์ํ๊ฒ ์ต๋๋ค. Board ์์ฑ์์ ์ด๊ธฐ state๋ฅผ ์์ ํ๋ ๊ฒ์ผ๋ก ๊ธฐ๋ณธ๊ฐ์ ์ค์ ํ ์ ์์ต๋๋ค.
class Board extends React.Component {
constructor(props) {
super(props);
this.state = {
squares: Array(9).fill(null),
xIsNext: true, };
}
ํ๋ ์ด์ด๊ฐ ์๋ฅผ ๋ ๋๋ง๋ค xIsNext
(boolean ๊ฐ)์ด ๋ค์งํ ๋ค์ ํ๋ ์ด์ด๊ฐ ๋๊ตฐ์ง ๊ฒฐ์ ํ๊ณ ๊ฒ์์ state๊ฐ ์ ์ฅ๋ ๊ฒ์
๋๋ค. Board์ handleClick
ํจ์๋ฅผ ์์ ํ์ฌ xIsNext
๊ฐ์ ๋ค์ง๊ฒ ์ต๋๋ค.
handleClick(i) {
const squares = this.state.squares.slice();
squares[i] = this.state.xIsNext ? 'X' : 'O'; this.setState({
squares: squares,
xIsNext: !this.state.xIsNext, });
}
์ด์ โXโ์ โOโ๋ ๋ฒ๊ฐ์ ๋ํ๋ฉ๋๋ค. ํ ๋ฒ ์๋ํด๋ณด์ธ์!
Board์ render
์์ ์๋ โstatusโ ํ
์คํธ๋ ๋ฐ๊ฟ์ ์ด๋ ํ๋ ์ด์ด๊ฐ ๋ค์ ์ฐจ๋ก์ธ์ง ์๋ ค์ฃผ๊ฒ ์ต๋๋ค.
render() {
const status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
return (
// ๋๋จธ์ง๋ ๊ทธ๋๋ก์
๋๋ค.
๋ณ๊ฒฝ์ฌํญ์ ์ ์ฉํ๋ฉด Board ์ปดํฌ๋ํธ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
class Board extends React.Component {
constructor(props) {
super(props);
this.state = {
squares: Array(9).fill(null),
xIsNext: true, };
}
handleClick(i) {
const squares = this.state.squares.slice(); squares[i] = this.state.xIsNext ? 'X' : 'O'; this.setState({ squares: squares, xIsNext: !this.state.xIsNext, }); }
renderSquare(i) {
return (
<Square
value={this.state.squares[i]}
onClick={() => this.handleClick(i)}
/>
);
}
render() {
const status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
return (
<div>
<div className="status">{status}</div>
<div className="board-row">
{this.renderSquare(0)}
{this.renderSquare(1)}
{this.renderSquare(2)}
</div>
<div className="board-row">
{this.renderSquare(3)}
{this.renderSquare(4)}
{this.renderSquare(5)}
</div>
<div className="board-row">
{this.renderSquare(6)}
{this.renderSquare(7)}
{this.renderSquare(8)}
</div>
</div>
);
}
}
์ง๊ธ๊น์ง์ ์ ์ฒด ์ฝ๋ ํ์ธํ๊ธฐ
์น์ ๊ฒฐ์ ํ๊ธฐ
์ด์ ์ด๋ค ์ ์๊ฐ ๋ค์ ์ฐจ๋ก์ธ์ง ์๋ ค์ฃผ์์ผ๋ ์น๋ถ๊ฐ ๋๋ ๋์ ๋ ์ด์ ๋ ๊ณณ์ด ์์ ๋๋ฅผ ์๋ ค์ฃผ์ด์ผ ํฉ๋๋ค. ๋ค์์ ๋์ฐ๋ฏธ ํจ์๋ฅผ ๋ณต์ฌํ์ฌ ํ์ผ ์ตํ๋จ์ ๋ถ์ฌ๋ฃ์ผ์ธ์.
function calculateWinner(squares) {
const lines = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6],
];
for (let i = 0; i < lines.length; i++) {
const [a, b, c] = lines[i];
if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
return squares[a];
}
}
return null;
}
9๊ฐ์ ์ฌ๊ฐํ์ ๋ฐฐ์ด์ ๊ฐ์ง๊ณ ํจ์๋ ์น์๋ฅผ ํ์ธํ์ฌ ์ ์ ํ ๊ฐ์ผ๋ก 'X'
, 'O'
, ๋๋ null
์ ๋ฐํํฉ๋๋ค.
์ด๋ค ํ๋ ์ด์ด๊ฐ ์ฐ์นํ๋์ง ํ์ธํ๊ธฐ ์ํด Board์ render
ํจ์์์ calculateWinner(squares)
๋ฅผ ํธ์ถํ ๊ฒ์
๋๋ค. ํ ํ๋ ์ด์ด๊ฐ ์ด๊ธด๋ค๋ฉด โWinner: Xโ ๋๋ โWinner: Oโ ๊ฐ์ ๋ฌธ๊ตฌ๋ฅผ ํ์ํ ์ ์์ต๋๋ค. Board์ render
ํจ์์์ ์ ์ธํ status
๋ฅผ ์๋ ์ฝ๋๋ก ๋ฐ๊ฟ์ฃผ์ธ์.
render() {
const winner = calculateWinner(this.state.squares); let status; if (winner) { status = 'Winner: ' + winner; } else { status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O'); }
return (
// ๋๋จธ์ง๋ ๊ทธ๋๋ก์
๋๋ค.
๋๊ตฐ๊ฐ๊ฐ ์น๋ฆฌํ๊ฑฐ๋ Square๊ฐ ์ด๋ฏธ ์ฑ์์ก๋ค๋ฉด Board์ handleClick
ํจ์๊ฐ ํด๋ฆญ์ ๋ฌด์ํ๋๋ก ๋ณ๊ฒฝํ๊ฒ ์ต๋๋ค.
handleClick(i) {
const squares = this.state.squares.slice();
if (calculateWinner(squares) || squares[i]) { return; } squares[i] = this.state.xIsNext ? 'X' : 'O';
this.setState({
squares: squares,
xIsNext: !this.state.xIsNext,
});
}
์ง๊ธ๊น์ง์ ์ ์ฒด ์ฝ๋ ํ์ธํ๊ธฐ
์ถํํฉ๋๋ค! ์ด์ ์ ๋๋ก ๋์ํ๋ ํฑํํ ๊ฒ์์ ๋ง๋ค์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ React์ ๊ธฐ๋ณธ๋ ๋ฐฐ์ ์ต๋๋ค. ์ฌ๊ธฐ์ ์ง์ ํ ์น์๋ ์ฌ๋ฌ๋ถ์ธ ๊ฒ ๊ฐ๋ค์.
์๊ฐ ์ฌํ ์ถ๊ฐํ๊ธฐ
๋ง์ง๋ง ์ฐ์ต์ผ๋ก ๊ฒฝ๊ธฐ์์ ์ด์ ์ฐจ๋ก๋ก โ์๊ฐ์ ๋๋๋ฆฌ๊ธฐโ๋ฅผ ๋ง๋ค๊ฒ ์ต๋๋ค.
๋์์ ๋ํ ๊ธฐ๋ก ์ ์ฅํ๊ธฐ
squares
๋ฐฐ์ด์ ์ง์ ๋ณ๊ฒฝํ๋ค๋ฉด ์๊ฐ ์ฌํ์ ๊ตฌํํ๊ธฐ ์ด๋ ค์ ์ ๊ฒ์
๋๋ค.
ํ์ง๋ง slice()
๋ฅผ ์ฌ์ฉํด์ ๋งค ๋์ ์ดํ์ squares
๋ฐฐ์ด์ ์๋ก์ด ๋ณต์ฌ๋ณธ์ ๋ง๋ค์๊ณ ์ด๋ฅผ ๋ถ๋ณ ๊ฐ์ฒด๋ก ์ทจ๊ธํ์ต๋๋ค. ์ด๋ฅผ ํตํด ๊ณผ๊ฑฐ์ squares
๋ฐฐ์ด์ ๋ชจ๋ ๋ฒ์ ์ ์ ์ฅํ๊ณ ์ด๋ฏธ ์ง๋๊ฐ ์ฐจ๋ก๋ฅผ ํ์ํ ์ ์์ต๋๋ค.
๊ณผ๊ฑฐ์ squares
๋ฐฐ์ด๋ค์ history
๋ผ๋ ๋ค๋ฅธ ๋ฐฐ์ด์ ์ ์ฅํ ๊ฒ์
๋๋ค. history
๋ฐฐ์ด์ ์ฒซ ๋์๋ถํฐ ๋ง์ง๋ง ๋์๊น์ง ๋ชจ๋ ๊ฒ์ํ์ ์ํ๋ฅผ ํํํ๊ณ ์๋์ ๊ฐ์ ํํ์
๋๋ค.
history = [
// ์ฒซ ๋์์ด ๋ฐ์ํ๊ธฐ ์
{
squares: [
null, null, null,
null, null, null,
null, null, null,
]
},
// ์ฒซ ๋์์ด ๋ฐ์ํ ์ดํ
{
squares: [
null, null, null,
null, 'X', null,
null, null, null,
]
},
// ๋ ๋ฒ์งธ ๋์์ด ๋ฐ์ํ ์ดํ
{
squares: [
null, null, null,
null, 'X', null,
null, null, 'O',
]
},
// ...
]
์ด์ ์ด๋ค ์ปดํฌ๋ํธ๊ฐ history
state๋ฅผ ๊ฐ์ง๊ณ ์์ ์ง ๊ฒฐ์ ํด์ผ ํฉ๋๋ค.
๋ค์ State ๋์ด์ฌ๋ฆฌ๊ธฐ
์ด์ ๋์์ ๋ํ ๋ฆฌ์คํธ๋ฅผ ๋ณด์ฌ์ฃผ๋ ค๋ฉด ์ต์์ ๋จ๊ณ์ Game ์ปดํฌ๋ํธ๊ฐ ํ์ํฉ๋๋ค. history
๋ฅผ ์ด์ฉํด์ผํ๊ธฐ ๋๋ฌธ์ ์ต์์ ๋จ๊ณ Game ์ปดํฌ๋ํธ์ history
state๋ฅผ ๋๊ฒ ์ต๋๋ค.
history
state๋ฅผ Game ์ปดํฌ๋ํธ์ ๋์๊ธฐ ๋๋ฌธ์ ์์ Board ์ปดํฌ๋ํธ์์ squares
state๋ฅผ ๋ ์ด์ ์ฌ์ฉํ์ง ์์๋ ๋ฉ๋๋ค. Square ์ปดํฌ๋ํธ์์ Board ์ปดํฌ๋ํธ๋ก โstate๋ฅผ ๋์ด์ฌ๋ ธ๋ ๊ฒโ ์ฒ๋ผ ์ด๋ฒ์๋ Board์์ ์ต์์ ๋จ๊ณ Game ์ปดํฌ๋ํธ๋ก state๋ฅผ ๋์ด์ฌ๋ ธ์ต๋๋ค. ์ด๋ฅผ ํตํด Game ์ปดํฌ๋ํธ๋ Board์ ๋ฐ์ดํฐ๋ฅผ ์๋ฒฝํ ์ ์ดํ ์ ์์ผ๋ฉฐ history
์ ์ ์ฅ๋ ๊ณผ๊ฑฐ์ ์ฐจ๋ก๋ฅผ Board๊ฐ ๋ ๋๋ง ํ ์ ์๊ฒ ๋ง๋ญ๋๋ค.
์ฐ์ Game ์ปดํฌ๋ํธ์ ์์ฑ์ ์์ ์ด๊ธฐ state๋ฅผ ์ค์ ํด์ฃผ์ธ์.
class Game extends React.Component {
constructor(props) { super(props); this.state = { history: [{ squares: Array(9).fill(null), }], xIsNext: true, }; }
render() {
return (
<div className="game">
<div className="game-board">
<Board />
</div>
<div className="game-info">
<div>{/* status */}</div>
<ol>{/* TODO */}</ol>
</div>
</div>
);
}
}
๋ค์์ผ๋ก Game ์ปดํฌ๋ํธ์์ Board ์ปดํฌ๋ํธ๋ก squares
์ onClick
props๋ฅผ ์ ๋ฌํ๊ฒ ์ต๋๋ค. Board์์ ์ฌ๋ฌ ๊ฐ์ Square์ ์ฐ์ผ ๋จ์ผ ํด๋ฆญ ํธ๋ค๋ฌ๋ฅผ ๊ฐ์ก๊ธฐ ๋๋ฌธ์ ๊ฐ Square์ ์์น๋ฅผ onClick
ํธ๋ค๋ฌ์๊ฒ ๋๊ฒจ์ฃผ์ด ์ด๋ค Square๋ฅผ ํด๋ฆญํ๋์ง ํ์ํ ๊ฒ์
๋๋ค. Board ์ปดํฌ๋ํธ๋ฅผ ๋ณ๊ฒฝํ๋ ์์๋ ์๋์ ๊ฐ์ต๋๋ค.
constructor
๋ฅผ Board์์ ์ ๊ฑฐํด์ฃผ์ธ์.- Board์
renderSquare
์์this.state.squares[i]
๋ฅผthis.props.squares[i]
๋ก ๋ฐ๊ฟ์ฃผ์ธ์. - Board์
renderSquare
์์this.handleClick(i)
์this.props.onClick(i)
์ผ๋ก ๋ฐ๊ฟ์ฃผ์ธ์.
์ด์ Board ์ปดํฌ๋ํธ๋ ์๋์ ๊ฐ์ ํํ์ ๋๋ค.
class Board extends React.Component {
handleClick(i) {
const squares = this.state.squares.slice();
if (calculateWinner(squares) || squares[i]) {
return;
}
squares[i] = this.state.xIsNext ? 'X' : 'O';
this.setState({
squares: squares,
xIsNext: !this.state.xIsNext,
});
}
renderSquare(i) {
return (
<Square
value={this.props.squares[i]} onClick={() => this.props.onClick(i)} />
);
}
render() {
const winner = calculateWinner(this.state.squares);
let status;
if (winner) {
status = 'Winner: ' + winner;
} else {
status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
}
return (
<div>
<div className="status">{status}</div>
<div className="board-row">
{this.renderSquare(0)}
{this.renderSquare(1)}
{this.renderSquare(2)}
</div>
<div className="board-row">
{this.renderSquare(3)}
{this.renderSquare(4)}
{this.renderSquare(5)}
</div>
<div className="board-row">
{this.renderSquare(6)}
{this.renderSquare(7)}
{this.renderSquare(8)}
</div>
</div>
);
}
}
Game ์ปดํฌ๋ํธ์ render
ํจ์๋ฅผ ๊ฐ์ฅ ์ต๊ทผ ๊ธฐ๋ก์ ์ฌ์ฉํ๋๋ก ์
๋ฐ์ดํธํ์ฌ ๊ฒ์์ ์ํ๋ฅผ ํ์ธํ๊ณ ํ์ํ๊ฒ ์ต๋๋ค.
render() {
const history = this.state.history; const current = history[history.length - 1]; const winner = calculateWinner(current.squares); 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>{/* TODO */}</ol>
</div>
</div>
);
}
Game ์ปดํฌ๋ํธ๊ฐ ๊ฒ์์ ์ํ๋ฅผ ๋ ๋๋งํ๊ธฐ ๋๋ฌธ์ Board์ render
ํจ์์์ ์ค๋ณต๋๋ ์ฝ๋๋ฅผ ์ ๊ฑฐํ ์ ์์ต๋๋ค. ๋ฆฌํํ ๋ง ์ดํ์ Board์ render
ํจ์๋ ์๋์ ๊ฐ์ต๋๋ค.
render() { return ( <div> <div className="board-row"> {this.renderSquare(0)}
{this.renderSquare(1)}
{this.renderSquare(2)}
</div>
<div className="board-row">
{this.renderSquare(3)}
{this.renderSquare(4)}
{this.renderSquare(5)}
</div>
<div className="board-row">
{this.renderSquare(6)}
{this.renderSquare(7)}
{this.renderSquare(8)}
</div>
</div>
);
}
๋ง์ง๋ง์ผ๋ก handleClick
ํจ์๋ฅผ Board์์ Game ์ปดํฌ๋ํธ๋ก ์ด๋ํ๊ฒ ์ต๋๋ค. ๋ํ Game ์ปดํฌ๋ํธ์ state๊ฐ ๋ค๋ฅด๊ฒ ๊ตฌ์ฑ๋์ด์๊ธฐ ๋๋ฌธ์ handleClick
์ ์์ ํด์ผ ํฉ๋๋ค. Game์ handleClick
ํจ์์์ ์๋ก์ด ๊ธฐ๋ก ๋ชฉ๋ก์ history
๋ก ์ฐ๊ฒฐํ๊ฒ ์ต๋๋ค.
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, }]), xIsNext: !this.state.xIsNext,
});
}
์ฃผ์
๋ฐฐ์ด
push()
ํจ์์ ๊ฐ์ด ๋ ์ต์ํ ๋ฐฉ์๊ณผ ๋ฌ๋ฆฌconcat()
ํจ์๋ ๊ธฐ์กด ๋ฐฐ์ด์ ๋ณ๊ฒฝํ์ง ์๊ธฐ ๋๋ฌธ์ ์ด๋ฅผ ๋ ๊ถ์ฅํฉ๋๋ค.
ํ์ฌ ์์ ์์ Board ์ปดํฌ๋ํธ๋ renderSquare
์ render
ํจ์๋ง์ ํ์๋ก ํฉ๋๋ค. ๊ฒ์์ ์ํ์ handleClick
ํจ์๋ Game ์ปดํฌ๋ํธ๊ฐ ๊ฐ์ง๊ณ ์์ด์ผ ํฉ๋๋ค.
์ง๊ธ๊น์ง์ ์ ์ฒด ์ฝ๋ ํ์ธํ๊ธฐ
๊ณผ๊ฑฐ์ ์ด๋ ํ์ํ๊ธฐ
ํฑํํ ๊ฒ์์ ์ด๋ ์ ๋ณด๋ฅผ ๊ธฐ๋กํ๊ณ ์๊ธฐ ๋๋ฌธ์ ์ด์ ํ๋ ์ด์ด์๊ฒ ๊ณผ๊ฑฐ์ ์ด๋์ ๋ชฉ๋ก์ผ๋ก ํ์ํ ์ ์์ต๋๋ค.
์์์ React ์๋ฆฌ๋จผํธ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ๋ฌํ ์ ์๋ ํด๋์คํ JavaScript ๊ฐ์ฒด๋ผ๋ ๊ฒ์ ๋ฐฐ์ ์ต๋๋ค. React ์๋ฆฌ๋จผํธ ๋ฐฐ์ด์ ์ฌ์ฉํ๋ฉด ์ฌ๋ฌ ์์ดํ ์ ๋ ๋๋งํ ์ ์์ต๋๋ค.
JavaScript์์ ๋ฐฐ์ด์ ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฅธ ๋ฐ์ดํฐ์ ํจ๊ป ๋งคํํ ๋ ์ฌ์ฉํ๋ map()
ํจ์๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค. ์ด ํจ์๋ ์๋์ ๊ฐ์ด ์ฌ์ฉํ ์ ์์ต๋๋ค.
const numbers = [1, 2, 3];
const doubled = numbers.map(x => x * 2); // [2, 4, 6]
map
ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ์ด๋ ๊ธฐ๋ก์ ํ๋ฉด์ ํ์๋๋ React ๋ฒํผ ์๋ฆฌ๋จผํธ๋ก ๋งตํํ ์ ์์ผ๋ฉฐ ๊ณผ๊ฑฐ์ ์ด๋์ผ๋ก โ๋์๊ฐ๋โ ๋ฒํผ ๋ชฉ๋ก์ ํ์ํ ์ ์์ต๋๋ค.
๊ฒ์์ render
ํจ์์์ history
๋ฅผ map
ํด๋ณด๊ฒ ์ต๋๋ค.
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 ? 'Go to move #' + move : 'Go to game start'; return ( <li> <button onClick={() => this.jumpTo(move)}>{desc}</button> </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>
);
}
์ง๊ธ๊น์ง์ ์ ์ฒด ์ฝ๋ ํ์ธํ๊ธฐ
history
๋ฐฐ์ด์ ์ํํ๋ฉด์ step
๋ณ์๋ ํ์ฌ history
์์์ ๊ฐ์ ์ฐธ์กฐํ๋ฉฐ move
๋ ํ์ฌ history
์์์ ์ธ๋ฑ์ค๋ฅผ ์ฐธ์กฐํฉ๋๋ค. ์ง๊ธ์ move
์๋ง ๊ด์ฌ์ด ์์ผ๋ฏ๋ก step
์ ๋ค๋ฅธ ๊ณณ์ ํ ๋น๋์ง ์์ต๋๋ค.
ํฑํํ ๊ฒ์ ๊ธฐ๋ก์ ๊ฐ๊ฐ ์ด๋๋ง๋ค ๋ฒํผ <button>
์ ํฌํจํ๋ ๋ฆฌ์คํธ ์์ดํ
<li>
๋ฅผ ์์ฑํฉ๋๋ค. ๋ฒํผ์ this.jumpTo()
ํจ์๋ฅผ ํธ์ถํ๋ onClick
ํธ๋ค๋ฌ๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค. ์์ง์ jumpTo()
ํจ์๋ฅผ ๊ตฌํํ์ง ์์์ต๋๋ค. ์ง๊ธ ์ํ์์ ๊ฒ์์ ์ด๋ ๋ชฉ๋ก์ ์๋์ ๊ฐ์ ๊ฒฝ๊ณ ๋ฅผ ๊ฐ๋ฐ์ ๋๊ตฌ ์ฝ์์ ํ์ํฉ๋๋ค.
๊ฒฝ๊ณ ๋ฐฐ์ด์ด๋ ์ดํฐ๋ ์ดํฐ์ ์์๋ค์ ๊ณ ์ ์ โkeyโ prop์ ๊ฐ์ง๊ณ ์์ด์ผ ํฉ๋๋ค. โGameโ์ render ํจ์๋ฅผ ํ์ธํด์ฃผ์ธ์.
์์ ๊ฒฝ๊ณ ๊ฐ ๋ฌด์์ ์๋ฏธํ๋์ง ์๊ธฐํด๋ด ์๋ค.
Key ์ ํํ๊ธฐ
๋ฆฌ์คํธ๋ฅผ ๋ ๋๋งํ ๋ React๋ ๋ ๋๋งํ๋ ๋ฆฌ์คํธ ์์ดํ ์ ๋ํ ์ ๋ณด๋ฅผ ์ ์ฅํฉ๋๋ค. ๋ฆฌ์คํธ๋ฅผ ์ ๋ฐ์ดํธ ํ ๋ React๋ ๋ฌด์์ด ๋ณํ๋ ์ง ๊ฒฐ์ ํด์ผ ํฉ๋๋ค. ๋ฆฌ์คํธ์ ์์ดํ ๋ค์ ์ถ๊ฐ, ์ ๊ฑฐ, ์ฌ๋ฐฐ์ด, ์ ๋ฐ์ดํธ ๋ ์ ์์ต๋๋ค.
์๋์ ์ฝ๋๊ฐ
<li>Alexa: 7 tasks left</li>
<li>Ben: 5 tasks left</li>
๋ค์๊ณผ ๊ฐ์ด ๋ณํ๋ค๊ณ ์์ํด ๋ด ์๋ค.
<li>Ben: 9 tasks left</li>
<li>Claudia: 8 tasks left</li>
<li>Alexa: 5 tasks left</li>
์ฌ๋์ ๋์๋ task ๊ฐ์๊ฐ ์
๋ฐ์ดํธ๋์์ ๋ฟ๋ง ์๋๋ผ Alexa์ Ben์ ์์๊ฐ ๋ฐ๋๊ณ Claudia๊ฐ ๋ ์ฌ๋ ์ฌ์ด์ ์ถ๊ฐ๋์๋ค๊ณ ์๊ฐํ ๊ฒ์
๋๋ค. ๊ทธ๋ฌ๋ React๋ ์ปดํจํฐ ํ๋ก๊ทธ๋จ์ด๋ฉฐ ์ฌ๋์ด ์๋ํ ๋ฐ๊ฐ ๋ฌด์์ธ์ง ์์ง ๋ชปํฉ๋๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ๋ฆฌ์คํธ ์์ดํ
์ key prop์ ์ง์ ํ์ฌ ๊ฐ ์์ดํ
์ด ๋ค๋ฅธ ์์ดํ
๋ค๊ณผ ๋ค๋ฅด๋ค๋ ๊ฒ์ ์๋ ค์ฃผ์ด์ผ ํฉ๋๋ค. ํค๋ฅผ ์ง์ ํ๋ ํ ๊ฐ์ง ๋ฐฉ๋ฒ์ alexa
, ben
, claudia
๋ฌธ์๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์
๋๋ค. ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฌ์์ ํ์ํ๋ค๋ฉด Alexa, Ben, Claudia์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ID๊ฐ ํค๋ก ์ฌ์ฉ๋ ์ ์์ต๋๋ค.
<li key={user.id}>{user.name}: {user.taskCount} tasks left</li>
๋ชฉ๋ก์ ๋ค์ ๋ ๋๋งํ๋ฉด React๋ ๊ฐ ๋ฆฌ์คํธ ์์ดํ ์ ํค๋ฅผ ๊ฐ์ ธ๊ฐ๋ฉฐ ์ด์ ๋ฆฌ์คํธ ์์ดํ ์์ ์ผ์นํ๋ ํค๋ฅผ ํ์ํฉ๋๋ค. ํ์ฌ ๋ฆฌ์คํธ์์ ์ด์ ์ ์กด์ฌํ์ง ์๋ ํค๋ฅผ ๊ฐ์ง๊ณ ์๋ค๋ฉด React๋ ์๋ก์ด ์ปดํฌ๋ํธ๋ฅผ ์์ฑํฉ๋๋ค. ํ์ฌ ๋ฆฌ์คํธ๊ฐ ์ด์ ๋ฆฌ์คํธ์ ์กด์ฌํ๋ ํค๋ฅผ ๊ฐ์ง๊ณ ์์ง ์๋ค๋ฉด React๋ ๊ทธ ํค๋ฅผ ๊ฐ์ง ์ปดํฌ๋ํธ๋ฅผ ์ ๊ฑฐํฉ๋๋ค. ๋ ํค๊ฐ ์ผ์นํ๋ค๋ฉด ํด๋น ๊ตฌ์ฑ์์๋ ์ด๋ํฉ๋๋ค. ํค๋ ๊ฐ ์ปดํฌ๋ํธ๋ฅผ ๊ตฌ๋ณํ ์ ์๋๋ก ํ์ฌ React์๊ฒ ๋ค์ ๋ ๋๋งํ ๋ state๋ฅผ ์ ์งํ ์ ์๊ฒ ํฉ๋๋ค. ์ปดํฌ๋ํธ์ ํค๊ฐ ๋ณํ๋ค๋ฉด ์ปดํฌ๋ํธ๋ ์ ๊ฑฐ๋๊ณ ์๋ก์ด state์ ํจ๊ป ๋ค์ ์์ฑ๋ฉ๋๋ค.
React์์ key
๋ ์ฌํ ๊ธฐ๋ฅ์ธ ref
์ ๋์ผํ๊ฒ ํน๋ณํ๊ณ ๋ฏธ๋ฆฌ ์ง์ ๋ prop์
๋๋ค. ์๋ฆฌ๋จผํธ๊ฐ ์์ฑ๋๋ฉด React๋ key
์์ฑ์ ์ถ์ถํ์ฌ ๋ฐํ๋๋ ์๋ฆฌ๋จผํธ์ ์ง์ ํค๋ฅผ ์ ์ฅํฉ๋๋ค. key
๊ฐ props
์ ์ํ๋ ๊ฒ์ฒ๋ผ ๋ณด์ด์ง๋ง this.props.key
๋ก ์ฐธ์กฐํ ์ ์์ต๋๋ค. React๋ ์๋์ผ๋ก key
๋ฅผ ์ด๋ค ์ปดํฌ๋ํธ๋ฅผ ์
๋ฐ์ดํธ ํ ์ง ํ๋จํ๋ ๋ฐ์ ์ฌ์ฉํฉ๋๋ค. ์ปดํฌ๋ํธ๋ key
๋ฅผ ์กฐํํ ์ ์์ต๋๋ค.
๋์ ์ธ ๋ฆฌ์คํธ๋ฅผ ๋ง๋ค ๋๋ง๋ค ์ ์ ํ ํค๋ฅผ ํ ๋นํ ๊ฒ์ ๊ฐ๋ ฅํ๊ฒ ์ถ์ฒํฉ๋๋ค. ์ ์ ํ ํค๊ฐ ์๋ ๊ฒฝ์ฐ ๋ฐ์ดํฐ ์ฌ๊ตฌ์ฑ์ ๊ณ ๋ คํด ๋ณผ ์ ์์ต๋๋ค.
ํค๊ฐ ์ง์ ๋์ง ์์ ๊ฒฝ์ฐ React๋ ๊ฒฝ๊ณ ๋ฅผ ํ์ํ๋ฉฐ ๋ฐฐ์ด์ ์ธ๋ฑ์ค๋ฅผ ๊ธฐ๋ณธ ํค๋ก ์ฌ์ฉํฉ๋๋ค. ๋ฐฐ์ด์ ์ธ๋ฑ์ค๋ฅผ ํค๋ก ์ฌ์ฉํ๋ ๊ฒ์ ๋ฆฌ์คํธ ์์ดํ
์์๋ฅผ ๋ฐ๊พธ๊ฑฐ๋ ์์ดํ
์ ์ถ๊ฐ/์ ๊ฑฐ ํ ๋ ๋ฌธ์ ๊ฐ ๋ฉ๋๋ค. ๋ช
์์ ์ผ๋ก key={i}
๋ฅผ ์ ๋ฌํ๋ฉด ๊ฒฝ๊ณ ๊ฐ ๋ํ๋์ง๋ ์์ง๋ง ๋์ผํ ๋ฌธ์ ๋ฅผ ์ผ์ผํค๊ธฐ ๋๋ฌธ์ ๋๋ถ๋ถ์ ๊ฒฝ์ฐ์ ์ถ์ฒํ์ง ์์ต๋๋ค.
ํค๋ ์ ์ญ์์ ๊ณ ์ ํ ํ์๋ ์์ผ๋ฉฐ ์ปดํฌ๋ํธ์ ๊ด๋ จ ์์ดํ ์ฌ์ด์์๋ ๊ณ ์ ํ ๊ฐ์ ๊ฐ์ ธ์ผ ํฉ๋๋ค.
์๊ฐ ์ฌํ ๊ตฌํํ๊ธฐ
ํฑํํ ๊ฒ์์ ๊ธฐ๋ก์์ ๊ณผ๊ฑฐ์ ์ด๋ ์ ๋ณด๋ ์ด๋์ ์์ฐจ์ ์ธ ์ซ์๋ฅผ ๊ณ ์ ํ ID๋ก ๊ฐ์ก์ต๋๋ค. ์ด๋์ ์์๊ฐ ๋ฐ๋๊ฑฐ๋ ์ญ์ ๋๊ฑฐ๋ ์ค๊ฐ์ ์ฝ์ ๋ ์ ์๊ธฐ ๋๋ฌธ์ ์ด๋์ ์ธ๋ฑ์ค๋ฅผ ํค๋ก ์ฌ์ฉํด๋ ์์ ํฉ๋๋ค.
Game ์ปดํฌ๋ํธ์ render
ํจ์ ์์์ <li key={move}>
๋ก ํค๋ฅผ ์ถ๊ฐํ๋ฉด React์ ํค์ ๋ํ ๊ฒฝ๊ณ ๊ฐ ์ฌ๋ผ์ง ๊ฒ์
๋๋ค.
const moves = history.map((step, move) => {
const desc = move ?
'Go to move #' + move :
'Go to game start';
return (
<li key={move}> <button onClick={() => this.jumpTo(move)}>{desc}</button>
</li>
);
});
์ง๊ธ๊น์ง์ ์ ์ฒด ์ฝ๋ ํ์ธํ๊ธฐ
jumpTo
ํจ์๊ฐ ์ ์๋์ด์์ง ์๊ธฐ ๋๋ฌธ์ ๋ฆฌ์คํธ ์์ดํ
์ ๋ฒํผ์ ํด๋ฆญํ๋ฉด ์๋ฌ๊ฐ ๋ฐ์ํฉ๋๋ค. jumpTo
๋ฅผ ๊ตฌํํ๊ธฐ ์ ์ Game ์ปดํฌ๋ํธ์ state์ stepNumber
๋ฅผ ์ถ๊ฐํ์ฌ ํ์ฌ ์งํ ์ค์ธ ๋จ๊ณ๋ฅผ ํ์ํ๊ฒ ์ต๋๋ค.
๋จผ์ Game์ constructor
์ด๊ธฐ state๋ก stepNumber: 0
์ ์ถ๊ฐํด์ฃผ์ธ์.
class Game extends React.Component {
constructor(props) {
super(props);
this.state = {
history: [{
squares: Array(9).fill(null),
}],
stepNumber: 0, xIsNext: true,
};
}
๋ค์์ผ๋ก Game์ stepNumber
๋ฅผ ์
๋ฐ์ดํธํ๊ธฐ ์ํด jumpTo
๋ฅผ ์ ์ํด์ฃผ์ธ์. ๋ํ stepNumber
๊ฐ ์ง์์ผ ๋ ๋ง๋ค xIsNext
๋ฅผ true๋ก ์ค์ ํ๊ฒ ์ต๋๋ค.
handleClick(i) {
// ์ด ํจ์๋ ๋ณํ์ง ์์ต๋๋ค.
}
jumpTo(step) { this.setState({ stepNumber: step, xIsNext: (step % 2) === 0, }); }
render() {
// ์ด ํจ์๋ ๋ณํ์ง ์์ต๋๋ค.
}
jumpTo
ํจ์์์ state์ history
ํ๋กํผํฐ๋ฅผ ์
๋ฐ์ดํธํ์ง ์์์์ ์ฃผ๋ชฉํ์ธ์. ์ด๋ state์ ์
๋ฐ์ดํธ๊ฐ ๋ณํฉ๋๊ฑฐ๋ ๊ฐ๋จํ ๋งํด React๋ ๋๋จธ์ง state๋ฅผ ๊ทธ๋๋ก ๋๊ณ setState
ํจ์์ ์ธ๊ธ๋ ํ๋กํผํฐ๋ง ์
๋ฐ์ดํธํ๊ธฐ ๋๋ฌธ์
๋๋ค. ์์ธํ ๋ด์ฉ์ ๋ฌธ์๋ฅผ ์ฐธ์กฐํ์ธ์.
์ด์ ์ฌ๊ฐํ์ ํด๋ฆญํ ๋ ๋ง๋ค ์คํ๋๋ Game์ handleClick
ํจ์์ ๋ช ๊ฐ์ง ๋ณํ๋ฅผ ์ค ๊ฒ์
๋๋ค.
stepNumber
state๋ ํ์ฌ ์ฌ์ฉ์์๊ฒ ํ์๋๋ ์ด๋์ ๋ฐ์ํฉ๋๋ค. ์๋ก์ด ์ด๋์ ๋ง๋ ํ์ this.setState
์ ์ธ์๋ก stepNumber: history.length
๋ฅผ ์ถ๊ฐํ์ฌ stepNumber
๋ฅผ ์
๋ฐ์ดํธ ํด์ผ ํฉ๋๋ค. ์ด๋ฅผ ํตํด ์๋ก์ด ์ด๋์ด ์์ฑ๋ ํ์ ์ด๋์ด ๊ทธ๋๋ก ๋จ์์๋ ๊ฒ์ ๋ฐฉ์งํฉ๋๋ค.
๋ํ this.state.history
๋ฅผ this.state.history.slice(0, this.state.stepNumber + 1)
๋ก ๋ฐ๊ฟ๋๋ค. ์ด๊ฒ์ ์ฐ๋ฆฌ๊ฐ โ์๊ฐ์ ๋๋๋ คโ ๊ทธ ์์ ์์ ์๋ก์ด ์์ง์์ ๋ณด์ด๋ฉด, ์ง๊ธ์ ์ฌ๋ฐ๋ฅด์ง ์์ โ๋ฏธ๋โ์ ๊ธฐ๋ก์ ๋ชจ๋ ๋ฒ๋ฆฌ๋ ๊ฒ์ ๋ณด์ฅํฉ๋๋ค.
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,
});
}
๋ง์ง๋ง์ผ๋ก Game ์ปดํฌ๋ํธ์ render
ํจ์๋ฅผ ์์ ํ์ฌ ํญ์ ๋ง์ง๋ง ์ด๋์ ๋ ๋๋งํ๋ ๋์ stepNumber
์ ๋ง๋ ํ์ฌ ์ ํ๋ ์ด๋์ ๋ ๋๋งํ ๊ฒ์
๋๋ค.
render() {
const history = this.state.history;
const current = history[this.state.stepNumber]; const winner = calculateWinner(current.squares);
// the rest has not changed
๊ฒ์์ ๊ธฐ๋ก์์ ์ด๋ค ์ฐจ๋ก๋ฅผ ์ ํํ๋ค๋ฉด ํฑํํ ๊ฒ์ํ์ ์ฆ์ ์ ๋ฐ์ดํธํด์ ๊ทธ ๋จ๊ณ๊ฐ ๋ฐ์ํ ์งํ์ ๊ฒ์ํ์ ๋ณด์ฌ์ฃผ์ด์ผ ํฉ๋๋ค.
์ง๊ธ๊น์ง์ ์ ์ฒด ์ฝ๋ ํ์ธํ๊ธฐ
๋ง๋ฌด๋ฆฌ
์ถํํฉ๋๋ค! ์๋ ๊ธฐ๋ฅ์ ๊ฐ์ง ํฑํํ ๊ฒ์์ ๋ง๋ค์์ต๋๋ค.
- ํฑํํ ๋ฅผ ํ ์ ์๊ฒ ํด์ฃผ๊ณ ,
- ๊ฒ์์์ ์น๋ฆฌํ์ ๋๋ฅผ ์๋ ค์ฃผ๋ฉฐ,
- ๊ฒ์์ด ์งํ๋จ์ ๋ฐ๋ผ ๊ฒ์ ๊ธฐ๋ก์ ์ ์ฅํ๊ณ ,
- ํ๋ ์ด์ด๊ฐ ๊ฒ์ ๊ธฐ๋ก์ ํ์ธํ๊ณ ๊ฒ์ํ์ ์ด์ ๋ฒ์ ์ ๋ณผ ์ ์๋๋ก ํ์ฉํฉ๋๋ค.
์๊ณ ํ์ จ์ต๋๋ค! ์ด์ React๊ฐ ์ด๋ป๊ฒ ๋์ํ๋์ง ์ดํดํ์ จ๊ธธ ๋ฐ๋๋๋ค.
์ต์ข ๊ฒฐ๊ณผ๋ ์ฌ๊ธฐ์ ํ์ธํด์ฃผ์ธ์: ์ต์ข ๊ฒฐ๊ณผ.
์๊ฐ์ด ๋ ์๊ฑฐ๋ ์๋ก์ด React ๊ธฐ์ ์ ์ฐ์ตํ๊ณ ์ถ์ ๊ฒฝ์ฐ ๋ค์๊ณผ ๊ฐ์ด ๋์ด๋๋ฅผ ๋์ผ ์ ์๋ ํฑํํ ๊ฒ์ ๊ฐ์ ์์ด๋์ด๋ฅผ ๊ตฌํํด๋ณด์ธ์.
- ์ด๋ ๊ธฐ๋ก ๋ชฉ๋ก์์ ํน์ ํ์(ํ, ์ด)์ผ๋ก ๊ฐ ์ด๋์ ์์น๋ฅผ ํ์ํด์ฃผ์ธ์.
- ์ด๋ ๋ชฉ๋ก์์ ํ์ฌ ์ ํ๋ ์์ดํ ์ ๊ตต๊ฒ ํ์ํด์ฃผ์ธ์.
- ์ฌ๊ฐํ๋ค์ ๋ง๋ค ๋ ํ๋์ฝ๋ฉ ๋์ ์ ๋ ๊ฐ์ ๋ฐ๋ณต๋ฌธ์ ์ฌ์ฉํ๋๋ก Board๋ฅผ ๋ค์ ์์ฑํด์ฃผ์ธ์.
- ์ค๋ฆ์ฐจ์์ด๋ ๋ด๋ฆผ์ฐจ์์ผ๋ก ์ด๋์ ์ ๋ ฌํ๋๋ก ํ ๊ธ ๋ฒํผ์ ์ถ๊ฐํด์ฃผ์ธ์.
- ์น์๊ฐ ์ ํด์ง๋ฉด ์น๋ถ์ ์์ธ์ด ๋ ์ธ ๊ฐ์ ์ฌ๊ฐํ์ ๊ฐ์กฐํด์ฃผ์ธ์.
- ์น์๊ฐ ์๋ ๊ฒฝ์ฐ ๋ฌด์น๋ถ๋ผ๋ ๋ฉ์์ง๋ฅผ ํ์ํด์ฃผ์ธ์.
์์ต์๋ฅผ ํตํด ์๋ฆฌ๋จผํธ, ์ปดํฌ๋ํธ, props, state๋ฅผ ํฌํจํ React์ ๊ฐ๋
์ ๋ค๋ฃจ์์ต๋๋ค. ๊ฐ ํญ๋ชฉ์ ๋ํ ์์ธํ ์ค๋ช
์ ๋ฌธ์์ ๋ค๋ฅธ ๋ถ๋ถ์ ์ฐธ์กฐํ์๊ธธ ๋ฐ๋๋๋ค. ์ปดํฌ๋ํธ์ ์ ์์ ๋ํ ์์ธํ ๋ด์ฉ์ React.Component
API ์ฐธ์กฐ๋ฅผ ํ์ธํด์ฃผ์ธ์.