React Router DOM
을 설치 후 import 구문을 이용하여 BrowserRouter
, Routes
, Route
, Link
컴포넌트를 불러온다.
import { BrowserRouter, Routes, Route, Link } from 'react-router-dom';
🤔 import할 때 왜 어떤 건 중괄호를 사용하고 어떤 건 사용하지 않을까? 출처
해당 컴포넌트에서export
할 때,export
뒤에default
키워드를 붙여주면 다른 컴포넌트에서 import할 때 괄호를 써주지 않아도 된다. 또 변수명도 import한 컴포넌트에서 마음대로 지정할 수 있다.
라우터 역할을 하는 BrowserRouter
컴포넌트를 작성하고, 그 안에 경로를 매칭해주는 Routes
와 Route
, 그리고 경로를 변경하는 역할을 하는 Link를 작성한다.
<BrowserRouter>
<div className="App">
<main>
<section className="sidebar">
// <Link>의 to 속성을 활용하여 <Route> 컴포넌트에 설정해 준 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>
<section className="features">
<Routes>
// path로 경로를 설정해서 해당 경로로 접근하면 element에 작성한 컴포넌트로 연결해준다.
<Route path='/' element={<Tweets/>}></Route>
<Route path='/about' element={<About />}></Route>
<Route path='/mypage' element={<MyPage />}></Route>
</Routes>
</section>
</main>
</div>
</BrowserRouter>
트윗을 작성하기 위해 useState
로 사용자 이름과 메세지가 변경될 때마다 관리한다.
// useState 호출해서 state의 변수, 갱신 함수, 초기값을 지정한다.
const [username, setUsername] = useState("");
const handleChangeUser = (event) => {
// event를 호출한 요소의 값을 가져온다.
setUsername(event.target.value);
};
// input의 value가 변경될 때마다 호출될 함수를 지정한다.
<input
type="text"
placeholder="your username here.."
className="tweetForm__input--username"
onChange={handleChangeUser}
value={username}
></input>
트윗 전송 버튼을 클릭했을 때 트윗 목록에 작성한 트윗을 추가하기위해 트윗들을 state로 관리한다.
const [tweets, setTweets] = useState(dummyTweets);
const handleButtonClick = (event) => {
// 새로 추가할 트윗을 객체로 선언하고 작성했던 내용들을 할당한다.
const tweet = {id: ~, username: ~};
// 갱신 함수에 새 배열을 선언하고 새로 추가할 트윗과 기존 트윗을 spread 문법으로 펼쳐서 할당한다.
setTweets([tweet, ...tweets]);
// let new
// 트윗 전송 후 사용자 이름과 메세지를 비우기 위함
setUsername("");
setMsg("");
};
🤔 아래 코드처럼 unshift()를 써서 새 트윗을 기존 트윗에 추가해주면 안되나요?
tweets.unshift(tweet); setTweets(tweets);
unshift()는 원본 배열을 변경하는 것이기 때문에 기존에 저장된 tweets와 현재 갱신 함수에 전달 인자인 tweets는 주소가 같다. set 갱신함수는 같은 주소값이면 갱신을 하지 않기 때문에 리렌더링이 안된다!
🖐 저는 unshift()를 사용하고 싶은데요
const newTweets = tweets.slice(); newTweets.unshift(tweet); setTweets(newTweets);
unshift()를 사용하고 싶다면 위 코드처럼 tweets를 복사해 새 배열을 만들고(주소값이 달라짐) unshift()를 사용하면 된다
트윗들을 나열하기 위해 map을 사용해 tweets에서 꺼낸 각 tweet들을 Tweet 컴포넌트에 props으로 전달한다.
<ul className="tweets">
{
tweets.map(tweet => {
return <Tweet tweet={tweet} key={tweet.id}></Tweet>
})
}
</ul>
Tweet 컴포넌트에서는 객체인 props를 전달받아 렌더링한다.
const Tweet = ({ tweet }) => {
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>
</div>
<div className="tweet__message">
{tweet.content}
</div>
</div>
</li>
);
};