Section2 Unit6 [React] React State & Props - ๊ณผ์ Twittler State & Props
โญ๏ธ ๊ณผ์ . React Twittler State & Props
→ ๊ธฐ๋ณธ ๋ ์ด์์๊ณผ css๋ ์ฝ๋์คํ ์ด์ธ ์์ ์ค๋นํ ์ฝ๋๋ฅผ forkํด์ ๋ช๊ฐ์ง ๊ธฐ๋ฅ๋ง ๋ง๋ถ์ด๋ฉฐ ํ์ตํ๋ ๊ณผ์ ์๋ค.
→ ์์ธ ์ปดํฌ๋ํธ๋ฅผ ๊ตฌํํ๊ณ , map()์ ์ฌ์ฉํด ๋ฆฌ์คํธ๋ฅผ ์ถ๋ ฅํ๊ณ , React Router๋ฅผ ์ ์ฉํด SPA๋ฅผ ๊ตฌํํ์ผ๋ฉฐ, state์ props๋ฅผ ์ด์ฉํด Tweet ์ ์ก Form์ ๊ตฌํํ๋ค.
๐ ๊ตฌํ ๊ณผ์ ์ค Memo
1. defaultValue์ value
<input
type="text"
defaultValue="parkhacker"
placeholder="your username here.."
className="tweetForm__input--username"
value={username}
onChange={handleChangeUser}
></input>
→ defalutValue์ value๋ ํจ๊ป ์ฐ๋ฉด ๋ ์ค์ ํ๋๋ง ์ฐ๋ผ๊ณ ๊ฒฝ๊ณ ๊ฐ ๋จ. Warning: Tweets contains an input of type text with both value and defaultValue props. Input elements must be either controlled or uncontrolled (specify either the value prop, or the defaultValue prop, but not both). Decide between using a controlled or uncontrolled input element and remove one of these props.
๋ฆฌ์กํธ ๊ณต์๋ฌธ์์๋ “React ๋ ๋๋ง ๋ผ์ดํ์ฌ์ดํด์์ form ์์์ value ์์ฑ์ DOM์ ๊ฐ๋ณด๋ค ์ฐ์ ์ํฉ๋๋ค. ์ ์ด๋์ง์๋ ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ React๊ฐ ์ด๊ธฐ๊ฐ์ ์ง์ ํ๊ณ ํ์ ์ ๋ฐ์ดํธ๋ฅผ ์ ์ดํ์ง์๋ ๊ฒ์ด ์ข์ต๋๋ค. ์ด๋ฐ ์ผ์ด์ค๋ฅผ ๋ค๋ฃจ๊ธฐ ์ํด value ๋์ default value ์์ฑ์ ์ง์ ํ ์ ์์ต๋๋ค.” ๋ผ๊ณ ์ค๋ช ํ๋ค.
→ ์ฆ, ์ ์ด๋์ง ์๋ ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ default value ์์ฑ์ ์ง์ ํ ์ ์์ง๋ง, ์ง๊ธ์ input ์์๋ฅผ useState๋ก ์ํ ๋ณ๊ฒฝ์ ๋ฐ๋ฅธ ์ ์ด๋ฅผ ํด์ผ ํ๊ธฐ ๋๋ฌธ์ value๋ก ๋ฐ๊ฟ์ ์ฌ์ฉํ๋ค.
2. React์์ ์ํ ์ ๋ฐ์ดํธ
react์์ ์ํ๋ฅผ ์ ๋ฐ์ดํธ ํ ๋๋ ๋ถ๋ณ์ฑ์ ์ ์งํด์ผ ํ๋ค.
// ๊ธฐ์กด์ฝ๋
const Tweets = () => {
...
const [data, setData] = useState(dummyTweets);
const handleButtonClick = (event) => {
const newTweet = {
id: dummyTweets.length + 1,
username: username,
picture: "<https://randomuser.me/api/portraits/men/98.jpg>",
content: message,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
};
dummyTweets.push(newTweet);
setData(dummyTweets);
};
return (
...
);
};
↑ ์ ์ฝ๋์์ ํ๋ฉด ๋ฆฌ๋ ๋๋ง์ด ๋์ง ์๋ ์ด์
setData ํจ์์ ์๋ก์ด ๊ฐ์ ์ ๋ฌํด๋ ์ํ ์ ๋ฐ์ดํธ๊ฐ ์ด๋ฃจ์ด์ง์ง ์๊ธฐ ๋๋ฌธ. setData(dummyTweets)๋ฅผ ํธ์ถํ์ฌ๋ ์ํ(data)๋ ์ ๋ฐ์ดํธ๋์ง๋ง, ์ด๋ dummyTweets ๋ฐฐ์ด์ ๊ทธ๋๋ก ์ฐธ์กฐํ๋ ๊ฒ์ด๋ฏ๋ก React๊ฐ ์ํ ๋ณํ๋ฅผ ๊ฐ์งํ์ง ๋ชปํ๋ค.
React์์ ์ํ๋ฅผ ์ ๋ฐ์ดํธํ ๋๋ ๋ถ๋ณ์ฑ์ ์ ์งํด์ผ ํ๋ค. ๋ฐ๋ผ์ setData(dummyTweets) ๋์ ์ ์๋ก์ด ๋ฐฐ์ด์ ์์ฑํ๊ณ ์ด๋ฅผ ์ํ๋ก ์ค์ ํด์ผ ํ๋ค. ์ด๋ฅผ ์ํด ๋ฐฐ์ด์ concat() ๋ฉ์๋๋ ์ ๊ฐ ์ฐ์ฐ์(...)๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
โฌ๏ธ
// ๋ณ๊ฒฝ ์ฝ๋
const handleButtonClick = (event) => {
...
const newTweet = {
id: data.length + 1,
username: username,
picture: "<https://randomuser.me/api/portraits/men/98.jpg>",
content: message,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
};
const updatedTweets = [...data, newTweet];
setData(updatedTweets);
...
};
์ ์ฝ๋์์๋ data ๋ฐฐ์ด์ ์๋ก์ด ํธ์(newTweet)์ ์ถ๊ฐํ์ฌ ์๋ก์ด ๋ฐฐ์ด(updatedTweets)์ ์์ฑํ๊ณ , ์ด๋ฅผ setData ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ์ํ๋ก ์ค์ ํ๋ค. ์ด๋ ๊ฒ ํ๋ฉด ์ํ ์ ๋ฐ์ดํธ๊ฐ React์ ์ํด ๊ฐ์ง๋์ด ํ๋ฉด์ด ๋ฆฌ๋ ๋๋ง๋๋ค.
→ ํ์ง๋ง, username๊ณผ content๋ฅผ ๋ฐ๊ฟ๋๋ง๋ค ๋ถํ์ํ ๋ ๋๋ง์ด ๋๋ ๋ฌธ์ ๊ฐ ์๋ค. (๋์ค์ ๋ฐฐ์ฐ๊ฒ ์ง..?)
3. dummyTweet ์ ๋ ฌ
dummyTweets.sort((x, y) => x.id > y.id ? -1 : 1)
์ต์ ์์ผ๋ก ์ ๋ ฌํ๊ณ ์ถ์ด์ ์ปดํฌ๋ํธ ์๋จ์ ์ ๋ ฌ ๋จผ์ ํ๋ค.
์๋ก์ด ํธ์์ ์คํ๋ ๋ ์ฐ์ฐ์๋ก [newTweet, …data]
๋ก ์ถ๊ฐํ๋ ์ ํธ์์ ์๋ก ์ ๋ ฌ๋๋ค.
์ ํํ sorting์ ์ ๋ชปํ๊ฒ ๋๋ฐ, ์ฐ์ ์ด๋ ๊ฒ ํด๋๊ธฐ๋ก ํ๋ค.
→ ์ ๋ ฌ์ ํ๋๋ฐ ์ด๋ ์ปดํฌ๋ํธ์์ ํด์ผํ ์ง ๋ชฐ๋ผ์ ํค๋งธ์๋๋ฐ, ์ค๋ ์ค์ ๋ผ์ด๋ธ์ธ์ ๋ ์ง๋ฌธ์ ํ๋ค. dummydata๋ฅผ ๋ฐ๋ ์ปดํฌ๋ํธ์ธ Tweets ์ปดํฌ๋ํธ์์ ๋จผ์ ์ ๋ ฌ์ ํ๋ ๊ฒ์ธ์ง, ์๋๋ฉด dummydata๋ฅผ ๋ฐ์ list๋ก mapingํด ๋ณด์ฌ์ฃผ๋ Tweet ์ปดํฌ๋ํธ์์ ํ๋๊ฑด์ง ํท๊ฐ๋ ธ๊ธฐ ๋๋ฌธ์ด๋ค.
์ ๋ ฌ์ Tweets ์ปดํฌ๋ํธ ๋ด์์ ํ๋๊ฒ ๋ง๊ณ , ๋์ค์ ์๋ฒ์์ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ค๊ฒ ๋๋ฉด ์ ๋ ฌ๋ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ฌ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ์ ๋ ฌ์ ๊ดํ ๋ถ๋ถ์ ๋์ค์ ๋ค์ ๋ด๋ ๋๋ค๊ณ ํ๋ค. ์ํญ..?
4. sidebar์ ๋ค๋ฅธ ๋ฉ๋ด ํด๋ฆญ์ ๋ค์ dummydata๋ก ์ด๊ธฐํ
→ ๋ฐ์ดํฐ๋ ๋ณดํต ์๋ฒ์์ ๋ฐ์์ค๊ธฐ ๋๋ฌธ์, ์ด๋ฒ ์ ๋์์๋ ๋ฐ๋ก ์ ์ฅํด๋ ์๋ฒ๊ฐ ์์ผ๋ ๋ฆฌ๋ ๋๋ง๋๋ฉด useState์ ์ด๊ธฐ๊ฐ์ผ๋ก ์ค์ ํด๋ dummydata๋ง ๋ณด์ด๋๊ฒ ๋ง๋ค.
5. ์ญ์ ๋ฒํผ ๊ตฌํ
props๊ฐ ์ฌ์ ํ ํท๊ฐ๋ฆฌ๋ ๊ฑด์ง, ์ญ์ ๋ฒํผ ๊ตฌํํ๋๋ฐ๋ ์ฝ๋๋ฅผ ์ด๋์ ์์ฑํด์ผ ํ๋์ง๊ฐ ๊ฐ์ด ์ ์์กํ๋ค. ๊ทธ๋์ ์ ๋ฆฌํด ๋ณธ ๊ณผ์ .
• Tweets๊ฐ tweet list๋ฅผ ๊ฐ์ง๊ณ ์๋ ์์ ์ปดํฌ๋ํธ, Tweet์ ๊ฐ๋ณ tweet์ ๊ฐ์ง๊ณ ์๋ ํ์ ์ปดํฌ๋ํธ
• ์ด๋ฒคํธ๋ ํด๋น ์์ button
์ ๋ฑ๋กํด์ผ ํ๊ณ → Tweet ์ปดํฌ๋ํธ,
ํญ๋ชฉ์ ์ญ์ ํ์๋ ์ ์ฒด ๋ฆฌ์คํธ๋ฅผ ๋ฆฌ๋ ๋๋ง ํด์ผ ํ๋๊น (setData)
→ Tweets ์ปดํฌ๋ํธ
prop์ผ๋ก onDelete
๋ฅผ ์ ๋ฌํด ์คํํด์ผ ํ๋ค.
// Tweets.js
const Tweets = () => {
...
// ํด๋น๋๋ tweet์ ์ญ์ ํ๋ ํจ์
const handleDelete = (targetId) => {
console.log("DELETE ", targetId)
if (confirm("์ ๋ง ์ญ์ ํ์๊ฒ ์ต๋๊น?")) {
setData(data.filter((item) => item.id !== targetId ))
}
}
return (
<ul className="tweets">
{ data.map((list) => {
{/*
ํ์ ์ปดํฌ๋ํธ์์ ๋ฒํผ์ ํด๋ฆญ์, onDelete๋ฅผ ์์ ์ปดํฌ๋ํธ์์ ์ฐพ๊ฒ๋จ
{handleDelete}๋ ํด๋น ํธ์์ ์ญ์ ํ๋ ํจ์๋ก ์ด๋ ์คํ๋จ
*/}
return <Tweet tweet={list} key={list.id} onDelete={handleDelete} />
}) }
</ul>
)
...
}
// Tweet.js
const Tweet = ({ tweet, onDelete }) => { // onDelete๋ props๋ก Tweets์ผ๋ก ๋ถํฐ ์ ๋ฌ๋ฐ์
...
return (
<li className="tweet" id={tweet.id} >
...
{/*
๋ฒํผ ํด๋ฆญ์ onDelete๋ฅผ ๋ถ๋ฌ์ด (tweet์ id๊ฐ์ ๊ฐ์ง๊ณ )
onDelete๋ ์์ ์ปดํฌ๋ํธ์ธ Tweets์ ์์
*/}
<button onClick={() => onDelete(tweet.id)}>โ</button>
...
</li>
)
...
}
๐ฌ ๋ ธ์ ์ ์ ๋ฆฌํ ๋ด์ฉ์ ์ฎ๊ฒจ์ ์๊ฑด๋ฐ, ๋ค ๋ง๊ฒ ์ผ๋์ง ์ ๋ชจ๋ฅด๊ฒ ๋ค.
์ฝ์ผ์๋ ๋ถ ์์๊ฑธ๋ก ์์ํ์ง๋ง, ํน์ ํ๋ฆฐ ๋ถ๋ถ์ ๋ฐ๊ฒฌํ์ ๋ค๋ฉด.. ๋๊ธ๋ก ์๋ ค์ฃผ์ธ์..๐ซ
๐ฅ ๋์ค์ ์๊ฐ์ ์ฌ์ ๊ฐ ๋๋ฉด (๊ทธ๋ฐ ๋ ์ ์์ฌ๊ฒ ๊ฐ์ง๋ง) ์ง์ง ํธ์ํฐ์ฒ๋ผ ๋ค๋ฅธ ๊ธฐ๋ฅ๋ ๋ง๋ถ์ด๊ณ , CSS๋ ์ ์ฉ์ํค๊ณ ์ถ๋ค๋ ์๊ฐ์ด ๋ค์๋ค. ์ง๊ธ์ ํ ๊ฒ ๋ง์ผ๋, ์ฐ์ ๊ธฐ๋ก์ผ๋ก๋ง ๋จ๊ฒจ๋๊ธฐ๋ก *0*
๐ ์ค๋์ ํ๊ณ
์ง๋ ์ฃผ ๋ด๋ด ์ค์ตํ๋ ๋ฆฌ์กํธ twittler ๊ณผ์ ๊ฐ ์ค๋๋ก ๋ง๋ฌด๋ฆฌ๋๋ ๋ฏ ํ๋ค. ์ด๋ฒ์ ๊ฐ์ด ํ๊ฒ ๋ ํ์ด๋ถ์ ๊ฐ์ ํ๋๊ฑธ ์ ํธํ๋ ๊ฒ ๊ฐ์์ ์ฃผ๋ง๋์ ๊ณผ์ ๋ฅผ ๋ค ํ๊ณ , ์ค๋์ ์ญ์ ๋ฒํผ๋ ๊ตฌํํด๋ณด์๋ค. props๋ฅผ ์ดํดํ๋ค๊ณ ์๊ฐํ๋๋ฐ ๋ง์ ์ญ์ ๋ฒํผ์ ๊ตฌํํ๋ ค๋ ๋ ํท๊ฐ๋ ธ๋ค. ๊ทธ๋์ ์ ๋ฆฌ๋ฅผ ํด๋ณด์๋๋ฐ, ์ด๊ฒ ๋ค์๋ฒ ๋ฌด์ธ๊ฐ ๋ง๋ค๋ ๊ธฐ์ต์ ํ๊ณ ์์์ง๋ ์ ๋ชจ๋ฅด๊ฒ ๋ค. ๋ค๋ง, ํท๊ฐ๋ ธ๋ ๋ถ๋ถ์ ์ ๋ฆฌํ์ผ๋ ์ฐธ๊ณ ํ ์๋ ์์ง ์์๊น.
๋ฆฌ์กํธ์ ๋จ๋ฐฉํฅ ๋ฐ์ดํฐ ํ๋ฆ์ ๋ง์ถฐ props๋ฅผ ๋ถ๋ชจ ์ปดํฌ๋ํธ์์ ์์ ์ปดํฌ๋ํธ๋ก ํ๋จ๊ณ ํ๋จ๊ณ ์ ๋ฌํ๋๊ฒ, ์ด๋ค ๋ถ๋ถ์์๋ ๋ณต์กํ๊ฒ ๋๊ปด์ง๊ฑฐ๋ ๋นํจ์จ์ ์ธ ๊ฒ์ด ์๋๊ฐ, ์๊ฐ์ด ๋ค์๋ค. ๋ฌผ๋ก ๋ฆฌ์กํธ์ ์ด๋ฌํ ๋ถ๋ถ์ ํด์ํ๊ธฐ ์ํด ๋์ค์๋ ์ ์ญ ์ํ๊ด๋ฆฌ๋ฅผ ๋์์ฃผ๋ Redux๋ Context API ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋๋ ๋ฆฌ์กํธ์์ ์ ๊ณตํ๋ API๋ฅผ ์ฌ์ฉํ์ฌ ๋ ํจ์จ์ ์ธ ์ฝ๋๋ฅผ ์งค ์ ์๋๋ก ๋์์ค๋ค๊ณ ํ๋ค. ๋ฐ๋ง ์ด์ง ๋ด๊ถ์ ์ด๋ ํ ๋ฐฉ์์ผ๋ก ์ฝ๋๋ฅผ ์งฐ๋์ง ๊ธฐ์ต์ด ํ๋๋ ์๋์ง๋ง, ํ์คํ ๋ถํธํ๋ ๋ถ๋ถ์ ํด์์์ผ์คฌ๋ ๊ธฐ์ต์ ์๋ค.
๋์ค์ ํ์ต์๊ฐ์ ์ฌ์ ๊ฐ ๋๋ค๋ฉด ์ด๋ฒ์ ๋ง๋ค์๋ twittler ๊ณผ์ ์ ๊ธฐ๋ฅ์ ์ข ๋ ๋ง๋ถ์ฌ์ ํธ์ํฐ์ฒ๋ผ ๊ตฌํํด๋ณด๋ฉด ์ฌ๋ฐ์ ๊ฒ ๊ฐ๋ค๋ ์๊ฐ์ด ๋ค์๋ค ๐ (์ค๋ ์์ ๊ธฐ๋ฅ ๋ฃ๋ค๊ฐ ํฌ๊ธฐํ๋๋ฐ… ๐ญ ๋ค์ ํ ์ ์๊ฒ ์ง..?)
'Frontend Dev > ๐ฅ ์ฝ๋์คํ ์ด์ธ FE ๋ถํธ์บ ํ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Section2 Unit8 [HTTP/๋คํธ์ํฌ] ์ค์ต - REST API (0) | 2023.05.25 |
---|---|
Section2 Unit7 [HTTP/๋คํธ์ํฌ] ๊ธฐ์ด (0) | 2023.05.24 |
Section2 Unit6 [React] React State & Props (0) | 2023.05.22 |
Section2 Unit5 [React] React SPA (0) | 2023.05.19 |
Section2 Unit4 [React] Intro (0) | 2023.05.18 |