ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [React] ์‹ค์Šต - React Twittler State & Props
    codeStates front-end/React 2023. 1. 30. 20:30
    ๋ฐ˜์‘ํ˜•

     

     

     

    ๐Ÿ“Œ react twittler SPA

     

     

     

    ๐Ÿ“– ํ•™์Šต ๋ชฉํ‘œ

     

    React Router ์„ค์น˜

    • React Router๋ฅผ npm์œผ๋กœ ์„ค์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

    ์ƒ์„ธ ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ํ•˜๊ธฐ

    ์›ํ•˜๋Š” ๋ ˆ์ด์•„์›ƒ์— ๋ผ์›Œ ๋„ฃ์„ ์ˆ˜ ์žˆ๊ฒŒ ์ƒ์„ธ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋จผ์ € ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.

    Sidebar ์ปดํฌ๋„ŒํŠธ (Sidebar.js)

    • Sidebar ์ปดํฌ๋„ŒํŠธ๋Š” ์ด๋ฏธ ๊ตฌํ˜„๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. Sidebar.js ํŒŒ์ผ์—์„œ ์ง์ ‘ ํ™•์ธํ•˜์„ธ์š”.

    Footer ์ปดํฌ๋„ŒํŠธ (Footer.js)

    • Footer ์ปดํฌ๋„ŒํŠธ์˜ ํ›„์† ์—˜๋ฆฌ๋จผํŠธ๋กœ ์‹œ๋ฉ˜ํ‹ฑ ์—˜๋ฆฌ๋จผํŠธ <footer>๊ฐ€ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

    Tweet ์ปดํฌ๋„ŒํŠธ (Tweet.js)

    • ๊ฐ ํŠธ์œ—์— ๊ผญ ํ•„์š”ํ•œ ์ •๋ณด๋ฅผ ๋‹ด๊ณ  ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. (ํ”„๋กœํ•„ ์‚ฌ์ง„, ์œ ์ € ์ด๋ฆ„, ํŠธ์œ— ์ƒ์„ฑ ์ผ์ž, ํŠธ์œ— ๋ฉ”์‹œ์ง€)
      • ํ”„๋กœํ•„ ์‚ฌ์ง„์„ ๋„ฃ๊ธฐ ์œ„ํ•ด <img> ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ์ž‘์„ฑํ•˜๊ณ , src ์†์„ฑ์— ์ „๋‹ฌ๋ฐ›์€ props์˜ ์‚ฌ์ง„ ์ •๋ณด๊ฐ€ ๋“ค์–ด๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธํ•ด ์ฃผ์„ธ์š”.
      • ์œ ์ € ์ด๋ฆ„์„ ๋„ฃ๊ธฐ ์œ„ํ•ด <span> ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ์ž‘์„ฑํ•˜๊ณ , class ์ด๋ฆ„์„ tweet__username๋กœ ์ง€์ •ํ•˜์„ธ์š”.
      • ํŠธ์œ— ์ƒ์„ฑ ์ผ์ž๋ฅผ ๋„ฃ๊ธฐ ์œ„ํ•ด <span>์—˜๋ฆฌ๋จผํŠธ๋ฅผ ์ž‘์„ฑํ•˜๊ณ , class ์ด๋ฆ„์„ tweet__createdAt์œผ๋กœ ์ง€์ •ํ•˜์„ธ์š”.
        • ๋‚ ์งœ ํ˜•์‹์€ yyyy. mm. dd. ์ด์–ด์•ผ ํ•˜๊ณ , parsedDate ๋ณ€์ˆ˜๋ฅผ ์ด์šฉํ•˜์„ธ์š”.
      • ํŠธ์œ— ๋ฉ”์‹œ์ง€๋ฅผ ๋„ฃ๊ธฐ ์œ„ํ•ด <div> ์—˜๋ฆฌ๋จผํŠธ๊ฐ€ ์ž‘์„ฑ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. class ์ด๋ฆ„์„ tweet__message๋กœ ์ง€์ •๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•ด ์ฃผ์„ธ์š”.
        • ํŠธ์œ— ๋ฉ”์‹œ์ง€๋ฅผ div.tweet__message์˜ textContent๋กœ ๋„ฃ์Šต๋‹ˆ๋‹ค.
    • dummyTweets๊ฐ€ ์•„๋‹Œ ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ๊ฐ€ props๋กœ ์ „๋‹ฌ๋˜์–ด๋„ ํŠธ์œ— ์ •๋ณด๋ฅผ ์ •ํ™•ํ•˜๊ฒŒ ํ‘œ์‹œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

    ํŽ˜์ด์ง€ ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ํ•˜๊ธฐ

    ํŽ˜์ด์ง€๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.

    ์ด๋ฒˆ ๊ณผ์ œ์˜ ํ˜„์žฌ ์œ ์ €๋Š” parkhacker์ด๊ธฐ ๋•Œ๋ฌธ์—, Twittler์˜ MyPage์—์„œ parkhacker์˜ ํŠธ์œ—๋งŒ ๋ณด์—ฌ์•ผ ํ•˜๋Š” ์š”๊ตฌ์‚ฌํ•ญ์„ ๋งŒ์กฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

    About ์ปดํฌ๋„ŒํŠธ (About.js)

    • About ์ปดํฌ๋„ŒํŠธ์˜ ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋กœ Footer ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธํ•ด ์ฃผ์‹œ๊ณ , ์—†๋‹ค๋ฉด ์—ฐ๊ฒฐํ•ด ์ฃผ์„ธ์š”.

    MyPage ์ปดํฌ๋„ŒํŠธ (MyPage.js)

    • ์ฃผ์–ด์ง„ ํŠธ์œ— ๋ชฉ๋ก(dummyTweets)์ค‘ ํ˜„์žฌ ์œ ์ €์ธ parkhacker์˜ ํŠธ์œ—๋งŒ ๋ณด์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    • const ๋ณ€์ˆ˜๋กœ ์„ ์–ธ๋œ filteredTweets์„ ํ™œ์šฉํ•ด parkhacker์˜ ํŠธ์œ—์ด ๋ณด์ด๋„๋ก ๊ตฌํ˜„ํ•ด ์ฃผ์„ธ์š”.
    • MyPage ์ปดํฌ๋„ŒํŠธ์˜ ์ž์‹์ธ Tweet ์ปดํฌ๋„ŒํŠธ์— props๋กœ ๊ฐ ํŠธ์œ—์˜ ์ •๋ณด(dummyTweets์˜ ์š”์†Œ)๊ฐ€ ์ „๋‹ฌ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    • MyPage ์ปดํฌ๋„ŒํŠธ์˜ ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋กœ Footer ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

    MyPage๋Š” dummyTweets๋กœ ๊ตฌํ˜„๋œ ์ปดํฌ๋„ŒํŠธ์ž…๋‹ˆ๋‹ค.
    State&Props๋กœ ๊ตฌ์„ฑํ•œ ์ปดํฌ๋„ŒํŠธ์™€ ๋น„๊ตํ•˜์—ฌ ์™œ State&Props๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•˜๋Š”์ง€ ์ดํ•ดํ•ด๋ณด์„ธ์š”.

    Tweets ์ปดํฌ๋„ŒํŠธ (Tweets.js)

    • ํ•˜๋‚˜์˜ ํŠธ์œ—์ด ์•„๋‹ˆ๋ผ, ์ฃผ์–ด์ง„ ํŠธ์œ—(dummyTweets) ๊ฐœ์ˆ˜์— ๋งž๊ฒŒ ๋ณด์—ฌ์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    • Tweets ์ปดํฌ๋„ŒํŠธ์˜ ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋กœ Footer ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

    React Router ์ ์šฉํ•˜๊ธฐ

    ์ด์ „ React Twittler SPA ๊ณผ์ œ์—์„œ ๋ฐฐ์šด ๋‚ด์šฉ์„ ๋ฐ”ํƒ•์œผ๋กœ ์•„๋ž˜ ๊ธฐ์ˆ  ์š”๊ตฌ์‚ฌํ•ญ์„ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.

    React Router ์ปดํฌ๋„ŒํŠธ ์ ์šฉ

    • Route path๊ฐ€ "/" ์ธ Tweets ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    • Route path๊ฐ€ "/about" ์ธ About ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    • Route path๊ฐ€ "/mypage" ์ธ MyPage ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    • React Router์˜ Link ์ปดํฌ๋„ŒํŠธ๊ฐ€ 3๊ฐœ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    • Tweets ์•„์ด์ฝ˜์˜ Link ์ปดํฌ๋„ŒํŠธ๋Š” "/" ๋กœ ์—ฐ๊ฒฐ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    • About ์•„์ด์ฝ˜์˜ Link ์ปดํฌ๋„ŒํŠธ๋Š” "/about" ๋กœ ์—ฐ๊ฒฐ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    • MyPage ์•„์ด์ฝ˜์˜ Link ์ปดํฌ๋„ŒํŠธ๋Š” "/mypage" ๋กœ ์—ฐ๊ฒฐ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

    React Router๋กœ SPA ๊ตฌํ˜„ํ•˜๊ธฐ

    • ์ฒ˜์Œ ์ ‘์† ์‹œ, URL path๊ฐ€ / ์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    • About ๋ฉ”๋‰ด๋ฅผ ๋ˆ„๋ฅด๋ฉด URL path๊ฐ€ /about์œผ๋กœ ๋ผ์šฐํŠธ ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    • Mypage ๋ฉ”๋‰ด๋ฅผ ๋ˆ„๋ฅด๋ฉด URL path๊ฐ€ /mypage๋กœ ๋ผ์šฐํŠธ ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

    State, Props ํ™œ์šฉ ํŠธ์œ— ์ „์†ก Form ๋งŒ๋“ค๊ธฐ

    ์ด๋ฒˆ ๊ณผ์ œ์˜ ํ•ต์‹ฌ์ž…๋‹ˆ๋‹ค. Tweets ์ปดํฌ๋„ŒํŠธ์—์„œ ์–ด๋–ค ๋ฐ์ดํ„ฐ๊ฐ€ state๊ฐ€ ๋˜์–ด์•ผ ํ•˜๊ณ , ์–ด๋–ค ๋ฐ์ดํ„ฐ๋ฅผ props๋กœ ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ์— ์ „๋‹ฌํ•ด์•ผ ํ• ์ง€ ๊ณ ๋ฏผํ•˜๊ณ  ์•„๋ž˜ ๊ธฐ์ˆ  ์š”๊ตฌ์‚ฌํ•ญ์„ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค. State, Props ๋ ˆ์Šจ๊ณผ ์‹ค์Šต์ด ๋„์›€์ด ๋  ๊ฒ๋‹ˆ๋‹ค. ๐Ÿ˜‡

    Tweets.js ํŠธ์œ— ์ „์†ก Form ํ…Œ์ŠคํŠธ

    • ์œ ์ € ์ด๋ฆ„์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋Š” input ์—˜๋ฆฌ๋จผํŠธ๊ฐ€ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. (className : "tweetForm__input--username")
    • <input>์˜ ๊ฐ’์ด ๋ณ€๊ฒฝ๋  ๋•Œ onChange ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ๋ถˆ๋ ค์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    • ํŠธ์œ—์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋Š” textarea ์—˜๋ฆฌ๋จผํŠธ๊ฐ€ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. (className : "tweetForm__input--message")
    • <textarea>์˜ ๊ฐ’์ด ๋ณ€๊ฒฝ๋  ๋•Œ onChange ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ๋ถˆ๋ ค์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    • ํŠธ์œ—์„ ์ „์†กํ•  ์ˆ˜ ์žˆ๋Š” button ์—˜๋ฆฌ๋จผํŠธ๊ฐ€ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. (className : "tweetForm__submitButton")
    • <button>์˜ ๊ฐ’์ด ๋ณ€๊ฒฝ๋  ๋•Œ onClick ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ๋ถˆ๋ ค์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    • ์œ ์ € ์ด๋ฆ„๊ณผ ํŠธ์œ—์„ ์ž‘์„ฑํ•˜๊ณ , ํŠธ์œ— ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ์ƒˆ๋กœ์šด ํŠธ์œ—์ด ์ถ”๊ฐ€๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
      • ๊ธฐ์กด dummyTweets๋ฅผ ๋ชจ๋‘ ๋ณด์—ฌ์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.
      • ์ƒˆ๋กœ ์ถ”๊ฐ€๋œ ํŠธ์œ—์„ ํฌํ•จํ•˜์—ฌ ๋ณด์—ฌ์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.
      • ์ƒˆ๋กœ ์ถ”๊ฐ€๋œ ํŠธ์œ—์ด ์ตœ์ƒ๋‹จ์— ์œ„์น˜ํ•˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

     

     

    ๋ณธ ์‹ค์Šต์€ ์ฝ”๋“œ์Šคํ…Œ์ด์ธ ์—์„œ ์ˆ˜ํ–‰ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

     

     

    ์ฝ”๋”ฉ๋ถ€ํŠธ์บ ํ”„ | ์ฝ”๋“œ์Šคํ…Œ์ด์ธ  - ๋น„์ „๊ณต์ƒ๋„ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค

    ์ฝ”๋”ฉ๋ถ€ํŠธ์บ ํ”„๋ฅผ ์ฐพ๋Š”๋‹ค๋ฉด? ๊ฐœ๋ฐœ์ž๋กœ ์ปค๋ฆฌ์–ด ์ „ํ™˜์„ ์œ„ํ•œ ์ฑ…์ž„์žˆ๋Š” ์ฝ”๋”ฉ ๊ต์œก ๊ธฐ๊ด€! ์„œ๋น„์Šค ๊ธฐํš์ž, ๊ทธ๋กœ์Šค ๋งˆ์ผ€ํ„ฐ, ๋ฐ์ดํ„ฐ ์‚ฌ์ด์–ธํ‹ฐ์ŠคํŠธ ๋“ฑ ๋‹ค์–‘ํ•œ ์ „๋ฌธ ์ปค๋ฆฌ์–ด์— ๋„์ „ํ•˜์„ธ์š”. ์ทจ์—… ์„ฑ๊ณต์˜ ํ›„๊ธฐ

    www.codestates.com

     

     

    ๋Œ€๋ถ€๋ถ„์˜ ๋‚ด์šฉ์€ ์•„๋ž˜ ์‹ค์Šต๊ณผ ๋น„์Šทํ•ฉ๋‹ˆ๋‹ค

     

    https://hwantech.tistory.com/181

     

    [React] ์‹ค์Šต - react twittler SPA

    ๐Ÿ“Œ react twittler SPA ๐Ÿ“– ํ•™์Šต ๋ชฉํ‘œ React Router ์„ค์น˜ react-router-dom ์„ npm์œผ๋กœ ์„ค์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ƒ์„ธ ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ํ•˜๊ธฐ App ๋ฃจํŠธ ์ปดํฌ๋„ŒํŠธ(App.js) import ๋ฅผ ์ด์šฉํ•˜์—ฌ Tweets, MyPage, About ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ถˆ๋Ÿฌ์˜ต

    hwantech.tistory.com

     

     

     

     

     

    + ์ถ”๊ฐ€๋‚ด์šฉ๋งŒ ๋ธ”๋กœ๊น…

     

     

    component/Tweet.js

     

    import React from 'react';
    import './Tweet.css';
    
    // dummyTweets๊ฐ€ ์•„๋‹Œ ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ๊ฐ€ props๋กœ ์ „๋‹ฌ๋˜์–ด๋„ ํŠธ์œ— ์ •๋ณด๋ฅผ ์ •ํ™•ํ•˜๊ฒŒ ํ‘œ์‹œ
    const Tweet = ({ tweet }) => {
      //๋‚ ์งœ ํ˜•์‹์€ yyyy. mm. dd. ์ด์–ด์•ผ ํ•˜๊ณ , parsedDate ๋ณ€์ˆ˜๋ฅผ ์ด์šฉ
      const parsedDate = new Date(tweet.createdAt).toLocaleDateString('ko-kr');
    
      return (
        <li className="tweet" id={tweet.id}>
          <div className="tweet__profile">
            <img src={tweet.picture} />
          </div>
          <div className="tweet__content">
            <div className="tweet__userInfo">
              <div className="tweet__userInfo--wrapper">
                {/* TODO : ์œ ์ ธ ์ด๋ฆ„์ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. */}
                {/* TODO : ํŠธ์œ— ์ƒ์„ฑ ์ผ์ž๊ฐ€ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. parsedDate๋ฅผ ์ด์šฉํ•˜์„ธ์š”. */}
                //์œ ์ € ์ด๋ฆ„์„ ๋„ฃ๊ธฐ ์œ„ํ•ด <span> ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ์ž‘์„ฑํ•˜๊ณ , class ์ด๋ฆ„์„ tweet__username๋กœ ์ง€์ •ํ•˜์„ธ์š”.
                <span className="tweet__username">{tweet.username}</span>
                //ํŠธ์œ— ์ƒ์„ฑ ์ผ์ž๋ฅผ ๋„ฃ๊ธฐ ์œ„ํ•ด <span>์—˜๋ฆฌ๋จผํŠธ๋ฅผ ์ž‘์„ฑํ•˜๊ณ , class ์ด๋ฆ„์„ tweet__createdAt์œผ๋กœ ์ง€์ •
                <span className="tweet__createdAt">{parsedDate}</span>
              </div>
            </div>
            <div className="tweet__message">
              {/* TODO : ํŠธ์œ— ๋ฉ”์„ธ์ง€๊ฐ€ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. */}
             // ํŠธ์œ— ๋ฉ”์‹œ์ง€๋ฅผ div.tweet__message์˜ textContent๋กœ ๋„ฃ์Šต๋‹ˆ๋‹ค.
             {tweet.content}
            </div>
          </div>
        </li>
      );
    };
    
    export default Tweet;

     

     

    Pages/tweets.js

     

     

    // TODO : useState๋ฅผ react๋กœ ๋ถ€ํ„ฐ import ํ•ฉ๋‹ˆ๋‹ค.
    import React, { useState } from 'react';
    import Footer from '../Footer';
    import Tweet from '../Components/Tweet';
    import './Tweets.css';
    import dummyTweets from '../static/dummyData';
    
    const Tweets = () => {
      // TODO : ์ƒˆ๋กœ ํŠธ์œ—์„ ์ž‘์„ฑํ•˜๊ณ  ์ „์†กํ•  ์ˆ˜ ์žˆ๊ฒŒ useState๋ฅผ ์ ์ ˆํžˆ ํ™œ์šฉํ•˜์„ธ์š”.
      
      const getRandomNumber = (min, max) => {
        return parseInt(Math.random() * (Number(max) - Number(min) + 2));
      };
      
      const [user, setUser] = useState('parkhacker');
      const [msg, setMsg] = useState('');
      const [tweets, setTweets] = useState(dummyTweets);
      
      const handleButtonClick = (event) => {
        const tweet = {
          id: dummyTweets.length,
          username: user,
          picture: `https://randomuser.me/api/portraits/women/${getRandomNumber(
            1,
            98
          )}.jpg`,
          content :msg,
          createdAt : new Date().toLocaleDateString('ko-kr'),
          updatedAt : new Date().toLocaleDateString('ko-kr'),
          
    
        };
        // TODO : Tweet button ์—˜๋ฆฌ๋จผํŠธ ํด๋ฆญ์‹œ ์ž‘๋™ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์™„์„ฑํ•˜์„ธ์š”.
        // ํŠธ์œ— ์ „์†ก์ด ๊ฐ€๋Šฅํ•˜๊ฒŒ ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
        setTweets([tweet, ...tweets])
      };
      
    
      const handleChangeUser = (event) => {
        setUser(event.target.value)
        // TODO : Tweet input ์—˜๋ฆฌ๋จผํŠธ์— ์ž…๋ ฅ ์‹œ ์ž‘๋™ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์™„์„ฑํ•˜์„ธ์š”.
      };
    
      const handleChangeMsg = (event) => {
        setMsg(event.target.value)
        // TODO : Tweet textarea ์—˜๋ฆฌ๋จผํŠธ์— ์ž…๋ ฅ ์‹œ ์ž‘๋™ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์™„์„ฑํ•˜์„ธ์š”.
      };
    
      return (
        <React.Fragment>
          <div className="tweetForm__container">
            <div className="tweetForm__wrapper">
              <div className="tweetForm__profile">
                <img src="https://randomuser.me/api/portraits/men/98.jpg" />
              </div>
              <div className="tweetForm__inputContainer">
                <div className="tweetForm__inputWrapper">
                  <div className="tweetForm__input">
    
    
                    <input
                      type="text"
                      defaultValue="parkhacker"
                      value={user}
                      placeholder="your username here.."
                      className="tweetForm__input--username"
                      onChange={handleChangeUser}
                    ></input>
                    TODO : ํŠธ์œ—์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋Š” textarea ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ์ž‘์„ฑํ•˜์„ธ์š”.
                  
                  
                  <textarea
    
                    defaultValue={""}
                    placeholder="your message here.."
                    className="tweetForm__input--message"
                    onChange={handleChangeMsg}
                    value={msg}
    
                  ></textarea></div>
    
    
                  <div className="tweetForm__count" role="status">
                    <span className="tweetForm__count__text">
                      {/* TODO : ํŠธ์œ— ์ด ๊ฐœ์ˆ˜๋ฅผ ๋ณด์—ฌ์ค„ ์ˆ˜ ์žˆ๋Š” Counter๋ฅผ ์ž‘์„ฑํ•˜์„ธ์š”. */}
                      {'total: ' + tweets.length}
                    </span>
                  </div>
                </div>
    
    
                <div className="tweetForm__submit">
                  <div className="tweetForm__submitIcon"></div>
                  {/* TODO : ์ž‘์„ฑํ•œ ํŠธ์œ—์„ ์ „์†กํ•  ์ˆ˜ ์žˆ๋Š” button ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ์ž‘์„ฑํ•˜์„ธ์š”. */}
                  <button className="tweetForm__submitButton" onClick={handleButtonClick}>Tweet</button>
                </div>
              </div>
            </div>
          </div>
    
    
          <div className="tweet__selectUser"></div>
          <ul className="tweets">
            {/* TODO : ํ•˜๋‚˜์˜ ํŠธ์œ—์ด ์•„๋‹ˆ๋ผ, ์ฃผ์–ด์ง„ ํŠธ์œ— ๋ชฉ๋ก(dummyTweets) ๊ฐฏ์ˆ˜์— ๋งž๊ฒŒ ๋ณด์—ฌ์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค. */}
            {tweets.map((el) => { 
              return (
                <Tweet tweet={el} />
              )})}
    
          </ul>
          <Footer />
        </React.Fragment>
      );
    };
    
    export default Tweets;

     

     

    Pages/MyPage.js

     

     

    import React from 'react';
    import Footer from '../Footer';
    import Tweet from '../Components/Tweet';
    import './MyPage.css';
    import dummyTweets from '../static/dummyData';
    
    const MyPage = () => {
      const filteredTweets = dummyTweets.filter((tweet) => {
        return tweet.username === 'parkhacker';
      })
      // TODO : ์ฃผ์–ด์ง„ ํŠธ์œ— ๋ชฉ๋ก(dummyTweets)์ค‘ ํ˜„์žฌ ์œ ์ ธ์ธ parkhacker์˜ ํŠธ์œ—๋งŒ ๋ณด์—ฌ์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    
      return (
        <section className="myInfo">
          <div className="myInfo__container">
            <div className="myInfo__wrapper">
              <div className="myInfo__profile">
                <img src={filteredTweets[0].picture} />
              </div>
              <div className="myInfo__detail">
                <p className="myInfo__detailName">
                  {filteredTweets[0].username} Profile
                </p>
                <p>28 ํŒ”๋กœ์›Œ 100 ํŒ”๋กœ์ž‰</p>
              </div>
            </div>
          </div>
          <ul className="tweets__mypage">
            <Tweet tweet={filteredTweets[0]}/>
            {/* TODO : ์ฃผ์–ด์ง„ ํŠธ์œ— ๋ชฉ๋ก(dummyTweets)์ค‘ ํ˜„์žฌ ์œ ์ ธ์ธ parkhacker์˜ ํŠธ์œ—๋งŒ ๋ณด์—ฌ์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค. */}
          </ul>
          <Footer />
        </section>
      );
    };
    
    export default MyPage;
    ๋ฐ˜์‘ํ˜•

    ๋Œ“๊ธ€

Designed by Tistory.