๐ ๋ฐ๋๋ผ ์คํฐ๋์์ ์งํํ ๋ฆฌ์กํธ ๊ตฌํ ๊ณผ์ ๋ฅผ ์ฌ๋ฆฝ๋๋ค.
- ๋ฆฌ์กํธ ๊ณ์ฐ๊ธฐ ๐ https://react-calculator-nuuco.netlify.app/
- ๋ฆฌ์กํธ ์ซ์์ผ๊ตฌ ๊ฒ์ ๐ https://react-number-baseball.netlify.app/
- ๋ฆฌ์กํธ ์๋์ฐจ ๊ฒฝ์ฃผ ๊ฒ์ ๐ https://react-racingcar.netlify.app/
- ๋ฆฌ์กํธ ์ํ๊ธฐ ๊ตฌํ ๐ https://react-vendingmachine.netlify.app/
์ฒ์ ๊ฒฝํํด๋ณธ ์ฝ๋ ๋ฆฌ๋ทฐ...! ํ์๋ถ๋ค๊ป ๋ฐ์ ํผ๋๋ฐฑ์ ์ค์ ๋ก ์ ์ฉํด๋ณด์๋ค.
์์ ๊ณผ์ 1๊ณผ 2 ์ํ ํ, @YHJ96 ๋์ '์ฝ๋ ์ง๊ธฐ ์ ๋จผ์ ์๊ฐํด๋ณด๋ ์ต๊ด์ ๋ค์ด๋ ๊ฒ ์ข๋ค.'๋ ์ด์ผ๊ธฐ๋ฅผ ๋ค์๋ค.
๐ ์ด๋ค ์์๋ฅผ ์ฝ๋๋ฅผ ์ง๊ณ ์ด๋ค ๋ก์ง์ ์ ์ฉ์์ผ์ผ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋์ง ๋ฏธ๋ฆฌ ์๊ฐํด๋ณด๊ธฐ!
๐ ๋ฆฌ์กํธ ์๋์ฐจ ๊ฒฝ์ฃผ ๊ฒ์ - ๐งฉ ์๊ฐ ์์
๐ ์ฒ์์๋ ๊ทธ๋ฅ ์ฌ์ฉ์๊ฐ ๋ค ๊ท์น์ ๋ง์ถฐ์ ์ ๋๋ก ์ ๋ ฅํ์ ๋๋ง ์๊ฐํ์!
-
์ฐ์ ํ์ํ state ๋ฅผ ํ์ ํ๋ค.
-
๊ธฐ๋ณธ์ ์ผ๋ก input ์ฐฝ์ด ๋ ๊ฐ๋๊น ๊ฐ๊ฐ state ๋ก ํ์ํ๊ฒ ์ง? ๊ทธ๋ฆฌ๊ณ ์คํ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ฌ์ฃผ๋ state ๋ ํ์.
-
์๋์ฐจ ์ด๋ฆ state ์ ์๋ํ ํ์ state, ๊ทธ๋ฆฌ๊ณ ์คํ ๊ฒฐ๊ณผ state ๋ฅผ ๋ง๋ ๋ค. (carsInput, tryNum, result)
-
์์ ๋ state๋ฅผ ๋ฐํ์ผ๋ก ์ ๋ ฅ๊ฐ์ ๋ฐ์์์ state์ ์ ์ฅํด์ฃผ๋ ๋ก์ง(์ด๋ฒคํธํธ๋ค๋ฌ)์ ๋จผ์ ์ง๋ฉด ๋๊ฒ ๊ตฌ๋. ์์ธ์ฒ๋ฆฌ๋ ๋์ค์ ์๊ฐ.
-
๊ฐ ๋ฒํผ๋ ํ์ํ ๊ธฐ๋ฅ์ด ์์ผ๋ ํด๋นํ๋ ์ด๋ฒคํธํธ๋ค๋ฌ๋ฅผ ๋ง๋ค์ด์ค์ผ๊ฒ ๋ค...
a) ์๋์ฐจ ์ด๋ฆ ํ์ธ ๋ฒํผ
-> ํด๋ฆญํ์ ๋, ์ ๋ ฅ๊ฐ ์ ํจ์ฑ ๊ฒ์ฌํด์ฃผ๋ฉด ๋๊ฒ ๋ค. alert ์ฐฝ ๋์ฐ๊ธฐ
-> ์์ธ์ฒ๋ฆฌ๋๊น ๋์ค์ ๊ตฌํํ์...
b) ์๋ํ ํ์ ํ์ธ ๋ฒํผ
-> ํด๋ฆญํ์ ๋, ์ ํจํ ์์ธ์ง ๊ฒ์ฌํ๊ณ (alert ์ฐฝ ๋์์ฃผ๊ธฐ) ์ ํจํ๋ฉด ๊ฒฝ์ฃผ๋ฅผ ์คํํ์.
-> ์์ธ์ฒ๋ฆฌ๋ ๋์ค์ ํ๋ค ์น๊ณ ์ผ๋จ ๋ฒํผ ํด๋ฆญ์ ๊ฒฝ์ฃผ ์คํํ๊ฒ๋ง ๋ง๋ค์ด ๋์... -
๋ ๊ฐ์ ์ด์ฉํด ๊ฒฝ์ฃผ๋ฅผ ํ๋ ํจ์๋ฅผ ๋ง๋ ๋ค. ๊ฒฝ์ฃผ ํจ์์ ๋ก์ง์ ์ด ์ ๋๋ฉด ๋๊ฒ ์ง?
a) ์๋์ ์ด๋ฆ์ ์ผํ ๊ธฐ์ค์ผ๋ก ๋๋ ์ ๋ฐฐ์ด๋ก ๋ง๋ค์ด์ค๋ค.
-> ๋ฐ๋ก ๊ฐ์ฒด๋ก ๋ง๋ค๋ฉด ์ ๋ ฅ ์์์ ๋ฐ๋ผ ๊ฒฐ๊ณผ๊ฐ์ด ๋์ค์ง ์์. (b, a, 12 ํ๋ฉด 12, a, b ์์๋ก ๋์ด)
b) ๊ทธ ๋ฐฐ์ด์ ์์๋ฅผ ํค๋ก ํ๋ ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด ์ค๋ค.
c) ์๋ ํ์ ๋งํผ for ๋ฌธ์ ๋๋ค.
d) ๊ฐ ์๋์ฐจ๊ฐ ๋๋คํจ์๋ฅผ ๋๋ ค 4์ด์์ด ๋์ค๋ฉด ํด๋น ์๋์ฐจ๋ฅผ ํค๋ก ํ๋ ๊ฐ์ +1
e) ํ ํ์ ์๋ํ ๋๋ง๋ค์ ๊ฐ์ฒด ๊ฐ์ ์คํ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ๋ก ์ ์ฅํด๋๋ค.
f) for ๋ฌธ์ด ๋๋๋ฉด ์ด์ ๊ฐ์ฒด์๋ ์ต์ข ๊ฒฐ๊ณผ๊ฐ ๋ด๊ฒจ์๋ค. ์ด ์ต์ข ๊ฒฐ๊ณผ๋ก ์ฐ์น์๋ฅผ ๋ฝ๋๋ค.
g) ๊ฐ ํ์๋ณ ๊ฒฐ๊ณผ + ์ฐ์น ๊ฒฐ๊ณผ๋ฅผ result ์ ์ ์ฅํด์ผ์ง. -
result ๊ฐ ๋ค ๋์์ผ๋๊น return ๋ถ๋ถ์ ์ด result๋ฅผ ๋ณด์ฌ์ฃผ๋ฉด ๋๊ฒ ๋ค.
---- ์์ธ ์ฒ๋ฆฌ ----
-
์๋์ฐจ ์ด๋ฆ ์์ธ์ฒ๋ฆฌ๋ฅผ ํ๋ค.
-> ์ผ๋จ, split(,)๋ก ๋ฐฐ์ด์ด ๋ด์์ค๊ณ ๊ฐ ์์๋ฅผ ๊ฒ์ฌํ๋ค.
-> ๋น ๊ฐ์ด ์๋์ง, ๊ณต๋ฐฑ์ด ์๋์ง, 5์๋ฅผ ์ด๊ณผํ๋์ง -
์๋ํ ํ์ ์์ธ์ฒ๋ฆฌ๋ฅผ ํ๋ค.
-> 0์ด๋ ์์๋ฉด alert
-> ์๋์ฐจ ์ด๋ฆ์ด ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ํต๊ณผ ๋ชปํ์ผ๋ฉด alert (์... ์ ํจ์ฑ ๊ฒ์ฌ ํต๊ณผ ์ฌ๋ถ ์ ์ฅํ๋ state ๋ ํ์ํ๊ฒ ๋ค....) -
์๋์ฐจ ์ด๋ฆ์ด ์ ํจ์ฑ ๊ฒ์ฌ ํต๊ณผํ๋์ง ์ฌ๋ถ ์ ์ฅํ๋ state๋ฅผ ๋ง๋ ๋ค. (isValid)
-
์๋์ฐจ ์ด๋ฆ ํ์ธ ๋ฒํผ ํด๋ฆญ์ ์ ํจ์ฑ ๊ฒ์ฌ ํต๊ณผํ ๊ฒฝ์ฐ๋ง ๊ฒฝ์ฃผ ์คํ.
๐คโ ๊ณ ๋ฏผ ๊ฑฐ๋ฆฌ
- ์๋์ฐจ ์ด๋ฆ state๋ฅผ ๋ฌธ์์ด๋ก ๋ฃ์ด์ค์ผ ์ข์๊น, ๋ฐฐ์ด์ ๋ฃ์ด์ค์ผ ์ข์๊น? input ๊ฐ์ ๋ฐ์์ค๋ state๋ ์ ์ ํด์ ๋ฃ๋๊ฒ ์ข์๊ฐ ์๋ ๊ทธ๋ฅ ๋ฃ๊ณ ์ธ ๋ ์ํฉ๋ง์ถฐ ์ ์ ?
- ๋๋ input ํ๊ทธ์ value ๊ฐ์ ๊ผญ ๋ฃ์ด์ฃผ๋๋ฐ, ๋ค๋ฅธ ์ฌ๋๋ ๋ฃ์ด์ฃผ๋์ง, ์ด๊ฒ ๊ผญ ํ์ํ๊ฑด์ง ๋ค๋ฅธ ์ฌ๋ ์ฝ๋ ํ์ธํด๋ณด์.
- ์ด๋ค ์ด๋ฒคํธ์์ ์ด๋ค ์ฒ๋ฆฌ๋ฅผ ํด์คํ๋์ง ํท๊ฐ๋ฆฐ๋ค. ์ข ๊ธฐํ ๋ถ๋ถ์ด๊ธด ํ๋ฐ...
-> ์ ๋ ฅํ ๋ ์๋ชป ์ ๋ ฅ์ ๋ฐ๋ก alert๊ฐ ์ข์๊น, ํ์ธ ๋ฒํผ ๋๋ฅธ ๋ค alert๊ฐ ์ข์๊น? - ์ฒ์์๋ result๋ฅผ ๊ฐํ๋ฌธ์๋ฅผ ๋ฃ์ ๋ฌธ์์ด๋ก ์ธํ
ํด์ {result}๋ก ํ๋ฒ์ ๋ณด์ฌ์ฃผ๋ ค ํ๋ค.
-> ํ์ง๋ง ๊ฐํ๋ฌธ์๊ฐ html ์์๋ ์ถ๋ ฅ๋์ง ์์๋ค. ํ์ค๋ก๋ง ๋์ด...
-><pre>{result}</pre>
๋ก ๋ฃ์ผ๋ฉด ์ค๋ฐ๊ฟ์ ๋๋, ํฐํธ ๋๋์ด ๋ฌ๋ผ์ ธ์ ๊ธฐ๊ฐ
-> ๊ทธ๋์ result๋ฅผ ๋ฐฐ์ด๋ก ๋ง๋ค๊ณ map์ ๋๋ ค ๊ฐ ๋ฌธ์์ด์<span>{item}<br/></span>
์ผ๋ก ์ถ๋ ฅ ํจ.
-> ๋ ์ข์ ๋ฐฉ๋ฒ์ ์์๊น?
==> ํด๊ฒฐ : css ๋ก white-space : pre ๋ฅผ ์ฃผ๋ฉด ํฐํธ๊ฐ ๋ฌ๋ผ์ง์ง ์๊ณ ๊ฐํ๋ฌธ์๊ฐ ์ ์ฉ๋๋ค!
===> ์ด๋ ๊ฒ<p style={{whiteSpace:"pre"}} >
(๊ฐํ๋ฌธ์ & ์ฐ์๊ณต๋ฐฑ ์ธ์) or pre-line(๊ฐํ๋ฌธ์๋ง ์ธ์, ์ฐ์๊ณต๋ฐฑ์ ํ๋๋ก ์ธ์) - result๋ฅผ map์ผ๋ก ๋ฟ๋ ค์ค ๋, ํค์ ์ธ๋ฑ์ค ๋ง๊ณ ๋ฌ๋ฆฌ ์ค๊ฒ ์๋...?
===> npm ์ nanoid, shortid ๋ชจ๋ ๋ค์ด๋ฐ์ ์ฌ์ฉ. ์ ๋ํฌํ ์์ด๋๊ฐ์ ์ฌ์ฉํ ์ ์๋ค. ํ์ง๋ง ์ด ๋ฌธ์ ์ ๊ฒฝ์ฐ ๋งค๋ฒ ๊ฐ์ด ๋ฐ๋๋ ์ด์ฐจํผ ๊ฒฐ๊ณผ ์ ์ฒด๋ฅผ ๋ฆฌ๋๋ํด์ผํด์ idx๋ก ๋ฃ์ด์ฃผ์๋ค.$ npm i shortid
import shortid from 'shortid'; ... //์ ์ฉ shortid.generate(); //ex) o5I6xwNG6j
๐ ๋ฆฌ์กํธ ์๋์ฐจ ๊ฒฝ์ฃผ ๊ฒ์ - ๐ ์ฝ๋ ๋ฆฌ๋ทฐ
-
handleCarsBtn ํธ๋ค๋ฌ๋ฅผ ๋ ์ต์ ํ ์ํค๋ฉด ์ข์ ๊ฒ ๊ฐ๋ค.
- ์ฒ์์ setIsValid(false) ๋ก ํ๊ณ ์์ธ์ฒ๋ฆฌ์์ ๊ฑธ๋ฆฌ๋ฉด return ํด๋ฒ๋ฆฌ๊ณ ๊ฑธ๋ฆฌ์ง ์์ผ๋ฉด ๋งจ ๋ง์ง๋ง์ setIsValid(false) ํด์ฃผ๋ฉด ์ฝ๋๋ฅผ ๋ ์ค์ผ ์ ์๋ค.
- ๋ํ alert ์ return ๋ฌธ์ ํฉ์น ์ ์๋ค.
return alert(...)
์ด๋ ๊ฒ. - ์๋๋ฉด ์ ๊ทํํ์์ ์จ์ ๋ ๊ฐ๋ตํ๊ฒ ์์ธ์ฒ๋ฆฌ ํด์ค ์ ์์ง ์์๊น?
- ๐ป ์ด์ ์ฝ๋
//car ์ข ๋ฅ ์ ๋ ฅ ํ์ธ ๋ฒํผ ํธ๋ค๋ฌ const handleCarsBtn = (e) => { e.preventDefault(); const tmp = carsInput.split(','); setIsValid(true); for(let car of tmp) { if(car === '') { alert('๋น ์ด๋ฆ์ด ์์ต๋๋ค.'); setIsValid(false); return; }else if(car.includes(' ')) { alert('๊ณต๋ฐฑ์ ํฌํจํ ์ ์์ต๋๋ค.'); setIsValid(false); return; }else if(car.length > 5) { alert('์ด๋ฆ์ 5์ ์ดํ๋ง ๊ฐ๋ฅํฉ๋๋ค.'); setIsValid(false); return; } } }
- ๐ป ๋ฆฌ๋ทฐ ๋ฐ์ 1
//car ์ข ๋ฅ ์ ๋ ฅ ํ์ธ ๋ฒํผ ํธ๋ค๋ฌ const handleCarsBtn = (e) => { e.preventDefault(); const tmp = carsInput.split(','); setIsValid(false); for(let car of tmp) { if(car === '') { return alert('๋น ์ด๋ฆ์ด ์์ต๋๋ค.'); }else if(car.includes(' ')) { return alert('๊ณต๋ฐฑ์ ํฌํจํ ์ ์์ต๋๋ค.'); }else if(car.length > 5) { return alert('์ด๋ฆ์ 5์ ์ดํ๋ง ๊ฐ๋ฅํฉ๋๋ค.'); } } setIsValid(true); }
- ๐ป ๋ฆฌ๋ทฐ ๋ฐ์ 2 : ์ ๊ท ํํ์ ์ฌ์ฉ
//car ์ข ๋ฅ ์ ๋ ฅ ํ์ธ ๋ฒํผ ํธ๋ค๋ฌ const handleCarsBtn = (e) => { e.preventDefault(); const tmp = carsInput.split(','); const regex = /^[^\s]{1,5}$/; setIsValid(false); for(let car of tmp) { if(!regex.test(car)) { return alert("์ด๋ฆ์ ๊ณต๋ฐฑ ๋ฏธํฌํจ 1 ~ 5์ ์ฌ์ด์ฌ์ผ ํฉ๋๋ค."); } } setIsValid(true); }
-
์ค์ฒฉ for ๋ฌธ๊ณผ ์ค์ฒฉ if ์ฌ์ฉ์ผ๋ก ๊ฐ๋ ์ฑ์ด ์ ์ข๋ค.
- ์ค์ฒฉ์ด ๋ง์์ง๋ ๋ถ๋ถ์ ๋ฐ๋ก ํจ์๋ก ๋นผ๋ ๋ ๊ฒ ๊ฐ๋ค.
- ๐ป ์ด์ ์ฝ๋
const tryArr = []; let max = 0; //์ฐ์น์๋ฅผ ๋ฝ๊ธฐ์ํด ์ต๋๊ฐ ๊ตฌํ๊ธฐ for(let i = 1; i <= tryNum; i++) { for(let car in carsObj) { const randomNumber = Random.pickNumberInRange(1, 9); if(randomNumber >= 4) { carsObj[car] += 1; if(max < carsObj[car]) { max = carsObj[car]; } } } tryArr.push(...createTryMsg(carsArr, carsObj)); tryArr.push('\n'); }
- ๐ป ๋ฆฌ๋ทฐ ๋ฐ์
const tryArr = []; for(let i = 1; i <= tryNum; i++) { tryOneRace(carsObj); tryArr.push(...createTryMsg(carsArr, carsObj)); tryArr.push('\n'); } ... //์ต๋๊ฐ ๊ตฌํ๋ ๋ก์ง์ ๋ง์ง๋ง ์๋๊ฐ ๋๋ ๋ค ์คํ let max = Math.max(...Object.values(carsObj)); ... //1ํ ๊ฒฝ์ฃผ ์คํ ํจ์ const tryOneRace = (carsObj) => { for(let car in carsObj) { const randomNumber = Random.pickNumberInRange(1, 9); if(randomNumber >= 4) { carsObj[car] += 1; } } }
๐ฅซ ๋ฆฌ์กํธ ์ํ๊ธฐ ๊ตฌํ - ๐ ์ฝ๋ ๋ฆฌ๋ทฐ
- props์ undefined ์ฒ๋ฆฌ๋ props๋ฅผ ๊ตฌ์กฐ๋ถํด ํ ๋น์ผ๋ก ๊ฐ์ ธ์ค๋ ๋ถ๋ถ์์ ๊ธฐ๋ณธ๊ฐ ์ฒ๋ฆฌ๋ฅผ ํด์ฃผ๋ฉด ๋๋ค.
- ๋ฆฌ๋ทฐ ๋ฐ์ ์
//Management.jsx {/* products && ๋ฅผ ๋ฃ์ด์ฃผ์ง ์์ผ๋ฉด 'map' undefined ๊ฐ ๋ฌ๋ค. (ํ ์คํธ์์๋ง) */} {/* ์ฒซ ๋ ๋๋ง์ products์ ๋ฐ์ดํฐ๊ฐ ์๋ค์ด์์ undefined ์ผ๋ map ๋ฉ์๋๋ฅผ ์จ์ ๋ฐ์ํ๋ ์ค๋ฅ */} {products && products.map((el, idx) => ( <tr key={idx}> <td>{el.product}</td> <td>{el.price}</td> <td>{el.count}</td> </tr> ))}
- ๋ฆฌ๋ทฐ ๋ฐ์ ํ
///Management.jsx function Management({products = [], setProducts}) { //๊ธฐ๋ณธ๊ฐ ์ฒ๋ฆฌ ... {products.map((el, idx) => ( <tr key={idx}> <td>{el.product}</td> <td>{el.price}</td> <td>{el.count}</td> </tr> ))} }
- ๋ฆฌ๋ทฐ ๋ฐ์ ์
e.target.reset()
์ ์ฌ์ฉํ๋ฉด ์ ๋ ฅํผ์ ์ด๊ธฐํ ์ํฌ ์ ์๋ค. ๋ฒํผ ๋๋ฅธ ํ ๊ฐ์ด ๋จ์์์ง ์๊ฒ ํ๊ธฐ์ํด ์ฌ์ฉํ๋ฉด ์ข๋ค.
=> ์ ๋ ฅ๊ฐ์ ๋ฐ์์ค๋ ์ด๋ฒคํธ ํธ๋ค๋ฌ์ ํ๋จ์e.target.reset()
๋ฅผ ์ถ๊ฐํด์ฃผ์๋ค.
ํ๊ทธ์ด๋ฆ | ์ค๋ช |
---|---|
feat | ์๋ก์ด ๊ธฐ๋ฅ ์ถ๊ฐ |
fix | ๋ฒ๊ทธ ์์ |
design | CSS ๋ฑ ์ฌ์ฉ์ UI ์์ |
style | ์ฝ๋ ํฌ๋งท ๋ณ๊ฒฝ, ์ธ๋ฏธ ์ฝ๋ก ๋๋ฝ, ์ฝ๋ ์์ ์ด ์๋ ๊ฒฝ์ฐ |
refactor | ์ฝ๋ ๋ฆฌํฉํ ๋ง |
comment | ์ฃผ์ ์ถ๊ฐ ๋ฐ ๋ณ๊ฒฝ |
docs | ๋ฌธ์ ์์ (MD ํ์ผ) |
chore | ๋น๋ ํ ์คํธ, ํจํค์ง ๋งค๋์ ์ค์ |
rename | ํ์ผ ํน์ ํด๋๋ช ์์ ํ๊ฑฐ๋ ์ฎ๊ธฐ๋ ์์ |
remove | ํ์ผ์ ์ญ์ ํ๋ ์์ ๋ง ํ๋ ๊ฒฝ์ฐ |
change | ๋ฌธ์๋ง ๋ณ๊ฒฝํ ๊ฒฝ์ฐ |