#은 컴포넌트
const dummyTweets = [
{
id: 1,
username: 'kimcoding',
picture: `https://randomuser.me/api/portraits/women/${getRandomNumber(
1,
98
)}.jpg`,
content:
'모든 국민은 인간으로서의 존엄과 가치를 가지며, 행복을 추구할 권리를 가진다. 모든 국민은 종교의 자유를 가진다. 국가는 농·어민과 중소기업의 자조조직을 육성하여야 하며, 그 자율적 활동과 발전을 보장한다. 모든 국민은 양심의 자유를 가진다. 누구든지 체포 또는 구속을 당한 때에는 즉시 변호인의 조력을 받을 권리를 가진다.',
createdAt: '2022-02-24T16:17:47.000Z',
updatedAt: '2022-02-24T16:17:47.000Z',
},
const MyPage = () => {
const filteredTweets = dummyTweets.filter(function (ele) {
return ele.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>
);
};
// filteredTweets : dummyTweets목록에서 username이 parkhacker인 것만 리턴함
// : filteredTweets의 0번째 인덱스만 Tweet 컴포넌트 적용
const App = (props) => {
return (
<BrowserRouter>
<div className="App">
<main>
<Sidebar />
<section className="features">
{/* TODO : 유어클래스를 참고해서, 테스트 케이스를 통과하세요.
TODO : React Router DOM 설치 후 BrowserRouter, Routes, Route의 주석을 해제하고 Routes, Route 컴포넌트를 적절하게 작성합니다. */}
{/* Route 예시: <Route path="/" element={<Tweets />}></Route> */}
<Routes>
<Route path ="/" element={<Tweets />}></Route>
<Route path ="/about" element={<About />}></Route>
<Route path ="/mypage" element={<Mypage />}></Route>
</Routes>
</section>
</main>
</div>
</BrowserRouter>
);
};
export default App;
// : history API를 사용해 URL과 UI를 동기화
: 여러 Route를 감싸서 그 중 규칙이 일치하는 라우트 단 하나만을 렌더링 시켜주는 역할
: 컴포넌트의 속성에 설정된 URL과 현재 경로가 일치하면 해당하는 컴포넌트, 함수를 렌더링한다. path속성에 경로, element속성에는 컴포넌트를 넣어 준다.
import React from 'react';
// TODO : React Router DOM의 Link 컴포넌트를 import 합니다.
import {Link} from 'react-router-dom';
const Sidebar = () => {
return (
<section className="sidebar">
{/* 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>
</section>
);
};
export default Sidebar;
: Link to를 통해 이동할 URL을 적어준다.
const Tweets = () => {
const [newTweet, newTweetcheck] = useState({ content: '', username: '' })
const [oldData, oldDatacheck] = useState(dummyTweets)
// TODO : 새로 트윗을 작성하고 전송할 수 있게 useState를 적절히 활용하세요.
const handleButtonClick = (event) => {
const tweet = {
...dummyTweets[0],
...newTweet
};
newTweetcheck({ content: '', username: '' });
oldDatacheck([tweet, ...oldData])
console.log(oldData)
// TODO : Tweet button 엘리먼트 클릭시 작동하는 함수를 완성하세요.
// 트윗 전송이 가능하게 작성해야 합니다.
};
const handleChangeUser = (event) => {
// TODO : Tweet input 엘리먼트에 입력 시 작동하는 함수를 완성하세요.
newTweetcheck({ ...newTweet, username: event.target.value })
console.log(event.target.value);
};
const handleChangeMsg = (event) => {
// TODO : Tweet textarea 엘리먼트에 입력 시 작동하는 함수를 완성하세요.
newTweetcheck({ ...newTweet, content: event.target.value })
console.log(event.target.value);
};
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"
placeholder="your username here.."
className="tweetForm__input--username"
onChange={handleChangeUser}
></input>
<textarea className="tweetForm__input--message" onChange={handleChangeMsg}>
</textarea>
</div>
<div className="tweetForm__count" role="status">
<span className="tweetForm__count__text">
{/* TODO : 트윗 총 개수를 보여줄 수 있는 Counter를 작성하세요. */}
{`total: ${dummyTweets.length}`}
</span>
</div>
</div>
<div className="tweetForm__submit">
<div className="tweetForm__submitIcon"></div>
{/* TODO : 작성한 트윗을 전송할 수 있는 button 엘리먼트를 작성하세요. */}
<button className="tweetForm__submitButton" onClick={handleButtonClick}> </button>
</div>
</div>
</div>
</div>
<div className="tweet__selectUser"></div>
<ul className="tweets">
{/* TODO : 하나의 트윗이 아니라, 주어진 트윗 목록(dummyTweets) 갯수에 맞게 보여줘야 합니다. */}
{oldData.map((tweet) => (
<Tweet tweet={tweet} />
))}
</ul>
<Footer />
</React.Fragment>
);
};
export default Tweets;
<input
type="text"
defaultValue="parkhacker"
placeholder="your username here.."
className="tweetForm__input--username"
onChange={handleChangeUser}
onChange={handleChangeUser} : (event) => { newTweetcheck({ ...newTweet, username: event.target.value }) : newTweet의 username 값에 입력하는 값 추가, console.log(event.target.value); : 입력 값 출력: textarea 값이 바뀔때마다 handleChangeMsg 실행 handleChangeMsg = (event) => { newTweetcheck({ ...newTweet, content: event.target.value }) : newTweet content 값에 textarea값을 할당 console.log(event.target.value); : 입력값 출력 }; : 버튼을 누를때마다 handleButtonClick이 실행됨 handleButtonClick = (event) => { const tweet = { ...dummyTweets[0], ...newTweet }; :tweet에 dummyTweets의 0번째 인덱스의 값을 할당, newtweet의 값 할당 newTweetcheck({ content: '', username: '' }); :newTweetcheck로 newTweet의 content, username을 빈 값으로 할당 oldDatacheck([tweet, ...oldData]) :oldDatacheck로 dummyTweets 값에 tweet 추가
{oldData.map((tweet) => (
))}
: oldData에서 Tweet 컴포넌트의 tweet 값을 가져옴
const Tweet = ({ tweet }) => {
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">
<span className="tweet__username">{tweet.username}</span>
<span className="tweet__createdAt">{parsedDate}</span>
{/* TODO : 유져 이름이 있어야 합니다. */}
{/* TODO : 트윗 생성 일자가 있어야 합니다. parsedDate를 이용하세요. */}
</div>
</div>
<div className="tweet__message">{tweet.content}
</div>
</div>
</li>
);
};