React ๊ธฐ์ดˆ (3) ๐Ÿฆ

forhreverยท2023๋…„ 3์›” 28์ผ
0

React Twittler State & Props ๊ณผ์ œ

https://github.com/forhrever/fe-sprint-react-twittler-state-props.git

React Router ์„ค์น˜

  • React Router๋ฅผ npm์œผ๋กœ ์„ค์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
npm install react-router-dom@6.3.0

**์ƒ์„ธ ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ํ•˜๊ธฐ(App.js)**

  • Route path๊ฐ€ "/" ์ธ Tweets ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • Route path๊ฐ€ "/about" ์ธ About ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • Route path๊ฐ€ "/mypage" ์ธ MyPage ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
// TODO : React Router DOM์„ ์„ค์น˜ ํ›„, import ๊ตฌ๋ฌธ์„ ์ด์šฉํ•˜์—ฌ BrowserRouter, Routes, Route ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ถˆ๋Ÿฌ์˜ต๋‹ˆ๋‹ค.
import {BrowserRouter, Routes, Route} from 'react-router-dom';
// TODO : MyPage, About ์ปดํฌ๋„ŒํŠธ๋ฅผ import ํ•ฉ๋‹ˆ๋‹ค.
import MyPage from './Pages/MyPage';
import About from './Pages/About';
{ /* TODO : React Router DOM ์„ค์น˜ ํ›„ BrowserRouter, Routes, Route์˜ ์ฃผ์„์„ ํ•ด์ œํ•˜๊ณ  Routes, Route ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ ์ ˆํ•˜๊ฒŒ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค. */}
{/* Route ์˜ˆ์‹œ: <Route path="/" element={<Tweets />}></Route> */}
      <Routes>
          <Route path="/" element={ <Tweets />} /> 
          <Route path="/mypage" element={<MyPage />} /> 
          <Route path="/about" element={<About />} />
      </Routes>
  • Tweets ์•„์ด์ฝ˜์˜ Link ์ปดํฌ๋„ŒํŠธ๋Š” "/" ๋กœ ์—ฐ๊ฒฐ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • About ์•„์ด์ฝ˜์˜ Link ์ปดํฌ๋„ŒํŠธ๋Š” "/about" ๋กœ ์—ฐ๊ฒฐ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • MyPage ์•„์ด์ฝ˜์˜ Link ์ปดํฌ๋„ŒํŠธ๋Š” "/mypage" ๋กœ ์—ฐ๊ฒฐ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
// TODO : React Router DOM์˜ Link ์ปดํฌ๋„ŒํŠธ๋ฅผ import ํ•ฉ๋‹ˆ๋‹ค.
import { Link } from 'react-router-dom';
{/* TODO : Link ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ž‘์„ฑํ•˜๊ณ , to ์†์„ฑ์„ ์ด์šฉํ•˜์—ฌ ๊ฒฝ๋กœ(path)๋ฅผ ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค. */}
      <Link to = "/"><i className="far fa-comment-dots"></i></Link>
      <Link to = "/about"><i className="far fa-question-circle"></i></Link>
      <Link to = "/mypage"><i className="far fa-user"></i></Link>
  • Footer ์ปดํฌ๋„ŒํŠธ์˜ ํ›„์† ์—˜๋ฆฌ๋จผํŠธ๋กœ ์‹œ๋ฉ˜ํ‹ฑ ์—˜๋ฆฌ๋จผํŠธ <footer>๊ฐ€ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
const Footer = () => {
  return <footer>Copyright from Codestates</footer>;
};
// TODO : Footer ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค. ์‹œ๋ฉ˜ํ‹ฑ ์š”์†Œ footer๊ฐ€ ํฌํ•จ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

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

  • ๊ฐ ํŠธ์œ—์— ๊ผญ ํ•„์š”ํ•œ ์ •๋ณด๋ฅผ ๋‹ด๊ณ  ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. (ํ”„๋กœํ•„ ์‚ฌ์ง„, ์œ ์ € ์ด๋ฆ„, ํŠธ์œ— ์ƒ์„ฑ ์ผ์ž, ํŠธ์œ— ๋ฉ”์‹œ์ง€)
    • ํ”„๋กœํ•„ ์‚ฌ์ง„์„ ๋„ฃ๊ธฐ ์œ„ํ•ด <img> ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ์ž‘์„ฑํ•˜๊ณ , src ์†์„ฑ์— ์ „๋‹ฌ๋ฐ›์€ props์˜ ์‚ฌ์ง„ ์ •๋ณด๊ฐ€ ๋“ค์–ด๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธํ•ด ์ฃผ์„ธ์š”.

      <div className="tweet__profile">
         <img src={tweet.picture} />
      </div>
    • ์œ ์ € ์ด๋ฆ„์„ ๋„ฃ๊ธฐ ์œ„ํ•ด <span> ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ์ž‘์„ฑํ•˜๊ณ , class ์ด๋ฆ„์„ tweet__username๋กœ ์ง€์ •ํ•˜์„ธ์š”.

      {/* TODO : ์œ ์ ธ ์ด๋ฆ„์ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. */}
          <span className="tweet__username">{tweet.username}</span>
    • ํŠธ์œ— ์ƒ์„ฑ ์ผ์ž๋ฅผ ๋„ฃ๊ธฐ ์œ„ํ•ด <span>์—˜๋ฆฌ๋จผํŠธ๋ฅผ ์ž‘์„ฑํ•˜๊ณ , class ์ด๋ฆ„์„ tweet__createdAt์œผ๋กœ ์ง€์ •ํ•˜์„ธ์š”.
      - ๋‚ ์งœ ํ˜•์‹์€ yyyy. mm. dd. ์ด์–ด์•ผ ํ•˜๊ณ , parsedDate ๋ณ€์ˆ˜๋ฅผ ์ด์šฉํ•˜์„ธ์š”.

      {/* TODO : ํŠธ์œ— ์ƒ์„ฑ ์ผ์ž๊ฐ€ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. parsedDate๋ฅผ ์ด์šฉํ•˜์„ธ์š”. */}
           <span className="tweet__createdAt">{parsedDate}</span>
    • ํŠธ์œ— ๋ฉ”์‹œ์ง€๋ฅผ ๋„ฃ๊ธฐ ์œ„ํ•ด <div> ์—˜๋ฆฌ๋จผํŠธ๊ฐ€ ์ž‘์„ฑ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. class ์ด๋ฆ„์„ tweet__message๋กœ ์ง€์ •๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•ด ์ฃผ์„ธ์š”.
      - ํŠธ์œ— ๋ฉ”์‹œ์ง€๋ฅผ div.tweet__message์˜ textContent๋กœ ๋„ฃ์Šต๋‹ˆ๋‹ค.

      <div className="tweet__message">
                { /* TODO : ํŠธ์œ— ๋ฉ”์„ธ์ง€๊ฐ€ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. */}
                {tweet.content}
      </div>

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

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

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

const MyPage = () => {
  const filteredTweets = dummyTweets.filter( (tweet) => {
    return tweet.username === "parkhacker";
  });
  // TODO : ์ฃผ์–ด์ง„ ํŠธ์œ— ๋ชฉ๋ก(dummyTweets)์ค‘ ํ˜„์žฌ ์œ ์ ธ์ธ parkhacker์˜ ํŠธ์œ—๋งŒ ๋ณด์—ฌ์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.
return ...

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

  • ์ฃผ์–ด์ง„ ํŠธ์œ— ๋ชฉ๋ก(dummyTweets)์ค‘ ํ˜„์žฌ ์œ ์ €์ธ parkhacker์˜ ํŠธ์œ—๋งŒ ๋ณด์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • const ๋ณ€์ˆ˜๋กœ ์„ ์–ธ๋œ filteredTweets์„ ํ™œ์šฉํ•ด parkhacker์˜ ํŠธ์œ—์ด ๋ณด์ด๋„๋ก ๊ตฌํ˜„ํ•ด ์ฃผ์„ธ์š”.
<ul className="tweets__mypage">
    <Tweet tweet={filteredTweets[0]}/>
{/* TODO : ์ฃผ์–ด์ง„ ํŠธ์œ— ๋ชฉ๋ก(dummyTweets)์ค‘ ํ˜„์žฌ ์œ ์ ธ์ธ parkhacker์˜ ํŠธ์œ—๋งŒ ๋ณด์—ฌ์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค. */}
</ul>

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

  • ํ•˜๋‚˜์˜ ํŠธ์œ—์ด ์•„๋‹ˆ๋ผ, ์ฃผ์–ด์ง„ ํŠธ์œ—(dummyTweets) ๊ฐœ์ˆ˜์— ๋งž๊ฒŒ ๋ณด์—ฌ์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.
<span className="tweetForm__count__text">
{/* TODO : ํŠธ์œ— ์ด ๊ฐœ์ˆ˜๋ฅผ ๋ณด์—ฌ์ค„ ์ˆ˜ ์žˆ๋Š” Counter๋ฅผ ์ž‘์„ฑํ•˜์„ธ์š”. */}
    {'total: ' + tweets.length}
</span>

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

  • ์œ ์ € ์ด๋ฆ„์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋Š” input ์—˜๋ฆฌ๋จผํŠธ๊ฐ€ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. (className : "tweetForm__input--username")
  • <input>์˜ ๊ฐ’์ด ๋ณ€๊ฒฝ๋  ๋•Œ onChange ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ๋ถˆ๋ ค์•ผ ํ•ฉ๋‹ˆ๋‹ค.
<div className="tweetForm__input">
<input
   type="text"
   defaultValue="parkhacker"
   placeholder="your username here.."
   className="tweetForm__input--username"
   onChange = {handleChangeMsg}
></input>
  • ํŠธ์œ—์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋Š” textarea ์—˜๋ฆฌ๋จผํŠธ๊ฐ€ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. (className : "tweetForm__input--message")
  • <textarea>์˜ ๊ฐ’์ด ๋ณ€๊ฒฝ๋  ๋•Œ onChange ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ๋ถˆ๋ ค์•ผ ํ•ฉ๋‹ˆ๋‹ค.
{ /* TODO : ํŠธ์œ—์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋Š” textarea ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ์ž‘์„ฑํ•˜์„ธ์š”. */} 
   <textarea
       defaultValue = {""}
       parkhacker = "your message here.."
       className = "tweetForm__input--message"
       onChange = {handleChangeMsg}
       value = {msg} 
    ></textarea>
  • ํŠธ์œ—์„ ์ „์†กํ•  ์ˆ˜ ์žˆ๋Š” button ์—˜๋ฆฌ๋จผํŠธ๊ฐ€ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. (className : "tweetForm__submitButton")
  • <button>์˜ ๊ฐ’์ด ๋ณ€๊ฒฝ๋  ๋•Œ onClick ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ๋ถˆ๋ ค์•ผ ํ•ฉ๋‹ˆ๋‹ค.
{/* TODO : ์ž‘์„ฑํ•œ ํŠธ์œ—์„ ์ „์†กํ•  ์ˆ˜ ์žˆ๋Š” button ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ์ž‘์„ฑํ•˜์„ธ์š”. */}
<button className='tweetForm__submitButton' onClick={handleButtonClick}>Tweet</button>
  • ์œ ์ € ์ด๋ฆ„๊ณผ ํŠธ์œ—์„ ์ž‘์„ฑํ•˜๊ณ , ํŠธ์œ— ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ์ƒˆ๋กœ์šด ํŠธ์œ—์ด ์ถ”๊ฐ€๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    • ๊ธฐ์กด dummyTweets๋ฅผ ๋ชจ๋‘ ๋ณด์—ฌ์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    • ์ƒˆ๋กœ ์ถ”๊ฐ€๋œ ํŠธ์œ—์„ ํฌํ•จํ•˜์—ฌ ๋ณด์—ฌ์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    • ์ƒˆ๋กœ ์ถ”๊ฐ€๋œ ํŠธ์œ—์ด ์ตœ์ƒ๋‹จ์— ์œ„์น˜ํ•˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.
<ul className="tweets">
{/* TODO : ํ•˜๋‚˜์˜ ํŠธ์œ—์ด ์•„๋‹ˆ๋ผ, ์ฃผ์–ด์ง„ ํŠธ์œ— ๋ชฉ๋ก(dummyTweets) ๊ฐฏ์ˆ˜์— ๋งž๊ฒŒ ๋ณด์—ฌ์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค. */}
{tweets.map((el) => { 
    return (
      <Tweet tweet={el} />
    )})}
</ul>

๊ตฌํ˜„๋œ ๋ชจ์Šต ( ๋ฉ”์‹œ์ง€ ์ž…๋ ฅ์ฐฝ์— โ€˜ํ–‰๋ณตํ•˜์žโ€™ ์ž…๋ ฅ ํ›„ Tweet ํ•œ ๊ฒฐ๊ณผ )


onChange

<input> <textarea> <select> ์™€ ๊ฐ™์€ ํผ(Form) ์—˜๋ฆฌ๋จผํŠธ๋Š” ์‚ฌ์šฉ์ž์˜ ์ž…๋ ฅ๊ฐ’์„ ์ œ์–ดํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

  • onChange์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด e.target.value๋ฅผ ํ†ตํ•ด ์ด๋ฒคํŠธ ๊ฐ์ฒด์— ๋‹ด๊ฒจ์žˆ๋Š” input๊ฐ’์„ ์ฝ์–ด์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด handleChangeํ•จ์ˆ˜๊ฐ€ ์ž‘๋™ํ•˜๋ฉฐ, ์ด๋ฒคํŠธ ๊ฐ์ฒด์— ๋‹ด๊ธด input๊ฐ’์„ setState๋ฅผ ํ†ตํ•ด ์ƒˆ๋กœ์šด state๋กœ ๊ฐฑ์‹ ํ•ฉ๋‹ˆ๋‹ค.
function NameForm() {
  const [name, setName] = useState("");

  const handleChange = (e) => {
    setName(e.target.value);
  }

  return (
    <div>
      <input type="text" value={name} onChange={handleChange}></input>
      <h1>{name}</h1>
    </div>
  )
};

onClick

onClick ์ด๋ฒคํŠธ๋Š” ๋ง ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉ์ž๊ฐ€ ํด๋ฆญ์ด๋ผ๋Š” ํ–‰๋™์„ ํ•˜์˜€์„ ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์ด๋ฒคํŠธ์ž…๋‹ˆ๋‹ค.

function NameForm() {
  const [name, setName] = useState("");

  const handleChange = (e) => {
    setName(e.target.value);
  }

  return (
    <div>
      <input type="text" value={name} onChange={handleChange}></input>
      <button onClick={alert(name)}>Button</button> // onClick 
      <h1>{name}</h1>
    </div>
  );
};
profile
๊ฐœ๋ฐœ์ž ์„ฑ์žฅ ๊ณ„๋‹จ ์˜ฌ๋ผ๊ฐ€๊ธฐ

0๊ฐœ์˜ ๋Œ“๊ธ€