https://github.com/forhrever/fe-sprint-react-twittler-state-props.git
npm install react-router-dom@6.3.0
// 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>
// 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>
๊ฐ ์์ด์ผ ํฉ๋๋ค.const Footer = () => {
return <footer>Copyright from Codestates</footer>;
};
// TODO : Footer ํจ์ ์ปดํฌ๋ํธ๋ฅผ ์์ฑํฉ๋๋ค. ์๋ฉํฑ ์์ footer๊ฐ ํฌํจ๋์ด์ผ ํฉ๋๋ค.
ํ๋กํ ์ฌ์ง์ ๋ฃ๊ธฐ ์ํด <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>
ํ์ด์ง๋ฅผ ๊ตฌ์ฑํ๋ ์ปดํฌ๋ํธ๋ฅผ ์์ฑํฉ๋๋ค.
์ด๋ฒ ๊ณผ์ ์ ํ์ฌ ์ ์ ๋ parkhacker์ด๊ธฐ ๋๋ฌธ์, Twittler์ MyPage์์ parkhacker์ ํธ์๋ง ๋ณด์ฌ์ผ ํ๋ ์๊ตฌ์ฌํญ์ ๋ง์กฑํด์ผ ํฉ๋๋ค.
const MyPage = () => {
const filteredTweets = dummyTweets.filter( (tweet) => {
return tweet.username === "parkhacker";
});
// TODO : ์ฃผ์ด์ง ํธ์ ๋ชฉ๋ก(dummyTweets)์ค ํ์ฌ ์ ์ ธ์ธ parkhacker์ ํธ์๋ง ๋ณด์ฌ์ค์ผ ํฉ๋๋ค.
return ...
filteredTweets
์ ํ์ฉํด parkhacker์ ํธ์์ด ๋ณด์ด๋๋ก ๊ตฌํํด ์ฃผ์ธ์.<ul className="tweets__mypage">
<Tweet tweet={filteredTweets[0]}/>
{/* TODO : ์ฃผ์ด์ง ํธ์ ๋ชฉ๋ก(dummyTweets)์ค ํ์ฌ ์ ์ ธ์ธ parkhacker์ ํธ์๋ง ๋ณด์ฌ์ค์ผ ํฉ๋๋ค. */}
</ul>
<span className="tweetForm__count__text">
{/* TODO : ํธ์ ์ด ๊ฐ์๋ฅผ ๋ณด์ฌ์ค ์ ์๋ Counter๋ฅผ ์์ฑํ์ธ์. */}
{'total: ' + tweets.length}
</span>
<input>
์ ๊ฐ์ด ๋ณ๊ฒฝ๋ ๋ onChange ์ด๋ฒคํธ ํธ๋ค๋ฌ๊ฐ ๋ถ๋ ค์ผ ํฉ๋๋ค.<div className="tweetForm__input">
<input
type="text"
defaultValue="parkhacker"
placeholder="your username here.."
className="tweetForm__input--username"
onChange = {handleChangeMsg}
></input>
<textarea>
์ ๊ฐ์ด ๋ณ๊ฒฝ๋ ๋ onChange ์ด๋ฒคํธ ํธ๋ค๋ฌ๊ฐ ๋ถ๋ ค์ผ ํฉ๋๋ค.{ /* TODO : ํธ์์ ์์ฑํ ์ ์๋ textarea ์๋ฆฌ๋จผํธ๋ฅผ ์์ฑํ์ธ์. */}
<textarea
defaultValue = {""}
parkhacker = "your message here.."
className = "tweetForm__input--message"
onChange = {handleChangeMsg}
value = {msg}
></textarea>
<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>
<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
์ด๋ฒคํธ๋ ๋ง ๊ทธ๋๋ก ์ฌ์ฉ์๊ฐ ํด๋ฆญ์ด๋ผ๋ ํ๋์ ํ์์ ๋ ๋ฐ์ํ๋ ์ด๋ฒคํธ์
๋๋ค.
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>
);
};