codeStates front-end/React
[React] ์ค์ต - react twittler SPA
ํํ
ํฌ
2023. 1. 25. 20:25
๋ฐ์ํ
๐ react twittler SPA
๐ ํ์ต ๋ชฉํ
React Router ์ค์น
- react-router-dom ์ npm์ผ๋ก ์ค์นํด์ผ ํฉ๋๋ค.
์์ธ ์ปดํฌ๋ํธ ๊ตฌํํ๊ธฐ
- App ๋ฃจํธ ์ปดํฌ๋ํธ(App.js)
- import ๋ฅผ ์ด์ฉํ์ฌ Tweets, MyPage, About ์ปดํฌ๋ํธ๋ฅผ ๋ถ๋ฌ์ต๋๋ค.
- Sidebar ๋ฉ๋ด ์ปดํฌ๋ํธ(Sidebar.js)
- Font Awesome์ ํ์ฉํ์ฌ About ์์ด์ฝ <i className="far fa-question-circle"></i>์ ๋ฃ์ด์ผ ํฉ๋๋ค.
- Font Awesome์ ํ์ฉํ์ฌ MyPage ์์ด์ฝ <i className="far fa-user"></i>์ ๋ฃ์ด์ผ ํฉ๋๋ค.
- Tweets ์ปดํฌ๋ํธ(Tweets.js)
- import ๋ฅผ ์ด์ฉํ์ฌ Footer ์ปดํฌ๋ํธ๋ฅผ ์ฐ๊ฒฐํฉ๋๋ค.
- dummyTweets์ ๊ธธ์ด๋งํผ ํธ์์ด ๋ณด์ฌ์ผ ํฉ๋๋ค
- MyPage ์ปดํฌ๋ํธ(MyPage.js)
- import ๋ฅผ ์ด์ฉํ์ฌ Footer ์ปดํฌ๋ํธ๋ฅผ ์ฐ๊ฒฐํฉ๋๋ค.
- kimcoding์ด ์์ฑํ ํธ์๋ง ๋ณด์ฌ์ผ ํฉ๋๋ค.
React Route ์ ์ฉํ๊ธฐ
- ๊ฐ ๋ฉ๋ด๋ฅผ ๋๋ ์ ๋, ์ฃผ์์ ๋ง๊ฒ ํ์ด์ง ๋ทฐ๊ฐ ๊ตฌํ๋์ด์ผ ํฉ๋๋ค.
์ปดํฌ๋ํธ๋ณ ๊ธฐ์ ์๊ตฌ์ฌํญ
- App ๋ฃจํธ ์ปดํฌ๋ํธ(App.js)
- <BrowserRouter>, <Routes>, <Route> ๋ก React Router ๋ฌธ๋ฒ์ ๋ง๊ฒ ์ปดํฌ๋ํธ๊ฐ ์์ด์ผ ํฉ๋๋ค.
- ์ฃผ์์ ๋ฐ๋ฅธ ํ์ด์ง๋ฅผ <Route> ์ปดํฌ๋ํธ๋ฅผ ์ด์ฉํ์ฌ ๊ตฌ๋ถ ์ง์ด ์ค๋๋ค.
- Tweets์ปดํฌ๋ํธ์ Route path๋ "/"์ ๋๋ค.
- About ์ปดํฌ๋ํธ์ Route path๋ "/about"์ ๋๋ค.
- MyPage ์ปดํฌ๋ํธ์ Route path๋ "/mypage"์ ๋๋ค.
- Sidebar ๋ฉ๋ด ์ปดํฌ๋ํธ(Sidebar.js)
- <Link> ์ปดํฌ๋ํธ์ to ์์ฑ์ ์ฌ์ฉํ์ฌ SPA ๋ด์์ ํ์ด์ง ์ ํ์ ๋ฐ๋ฅธ URL ์
๋ฐ์ดํธ๋ฅผ ์งํํด์ผ ํฉ๋๋ค.
- Tweets ์ปดํฌ๋ํธ์ Route path๋ "/"์ ๋๋ค.
- About ์ปดํฌ๋ํธ์ Route path๋ "/about"์ ๋๋ค.
- MyPage ์ปดํฌ๋ํธ์ Route path๋ "/mypage"์ ๋๋ค.
- <Link> ์ปดํฌ๋ํธ์ to ์์ฑ์ ์ฌ์ฉํ์ฌ SPA ๋ด์์ ํ์ด์ง ์ ํ์ ๋ฐ๋ฅธ URL ์
๋ฐ์ดํธ๋ฅผ ์งํํด์ผ ํฉ๋๋ค.
๋ณธ ์ค์ต์ ์ฝ๋์คํ ์ด์ธ ์์ ์ํํ์์ต๋๋ค.
์ฝ๋ฉ๋ถํธ์บ ํ | ์ฝ๋์คํ ์ด์ธ - ๋น์ ๊ณต์๋ ๊ฐ๋ฐ์๊ฐ ๋ ์ ์์ต๋๋ค
์ฝ๋ฉ๋ถํธ์บ ํ๋ฅผ ์ฐพ๋๋ค๋ฉด? ๊ฐ๋ฐ์๋ก ์ปค๋ฆฌ์ด ์ ํ์ ์ํ ์ฑ ์์๋ ์ฝ๋ฉ ๊ต์ก ๊ธฐ๊ด! ์๋น์ค ๊ธฐํ์, ๊ทธ๋ก์ค ๋ง์ผํฐ, ๋ฐ์ดํฐ ์ฌ์ด์ธํฐ์คํธ ๋ฑ ๋ค์ํ ์ ๋ฌธ ์ปค๋ฆฌ์ด์ ๋์ ํ์ธ์. ์ทจ์ ์ฑ๊ณต์ ํ๊ธฐ
www.codestates.com
๋ณธ ์ค์ต์ ์ํด ๊ฑด๋ค์ธ ์ฝ๋๋ ๋นจ๊ฐ ๋ฐ์ค ์ ๋๋ค.
App.js
import React from 'react';
import './App.css';
import './global-style.css';
// TODO - react-router-dom์ ์ค์น ํ, import ๊ตฌ๋ฌธ์ ์ด์ฉํ์ฌ BrowserRouter, Routes, Route ์ปดํฌ๋ํธ๋ฅผ ๋ถ๋ฌ์ค์ธ์.
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import Sidebar from './Sidebar';
import Tweets from './Pages/Tweets';
// TODO - import๋ฌธ์ ์ด์ฉํ์ฌ MyPage, About ์ปดํฌ๋ํธ๋ฅผ ๋ถ๋ฌ์ค์ธ์.
import About from './Pages/About';
import MyPage from './Pages/MyPage';
const App = () => {
return (
<div>
{/* TODO - BrowserRouter ์ปดํฌ๋ํธ๋ฅผ ์์ฑํฉ๋๋ค. */}
<BrowserRouter>
<div className="App">
<main>
<Sidebar />
<section className="features">
{/* TODO - Routes์ Route ์ปดํฌ๋ํธ๋ฅผ ์ด์ฉํ์ฌ ๊ฒฝ๋ก(path)๋ฅผ ์ค์ ํ๊ณ Tweets, Mypage, About ์ปดํฌ๋ํธ๋ฅผ ์ฐ๊ฒฐํฉ๋๋ค. */}
<Routes>
<Route path="/" element={<Tweets />} />
<Route path="/mypage" element={<MyPage />} />
<Route path="/about" element={<About />} />
</Routes>
</section>
</main>
</div>
</BrowserRouter>
</div>
);
};
// ! ์๋ ์ฝ๋๋ ์์ ํ์ง ์์ต๋๋ค.
export default App;
Sidebar.js
import React from 'react';
// TODO - import๋ฌธ์ ์ด์ฉํ์ฌ react-router-dom ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ Link ์ปดํฌ๋ํธ๋ฅผ ๋ถ๋ฌ์ต๋๋ค.
import {Link} from "react-router-dom";
const Sidebar = () => {
return (
<section className="sidebar">
{/* TODO : About ๋ฉ๋ด ์์ด์ฝ๊ณผ Mypage ๋ฉ๋ด ์์ด์ฝ์ ์์ฑํ๊ณ Link ์ปดํฌ๋ํธ๋ฅผ ์ด์ฉํ์ฌ ๊ฒฝ๋ก(path)๋ฅผ ์ฐ๊ฒฐํฉ๋๋ค. */}
<Link to="/">
<i className="far fa-comment-dots"></i> // className์ npm test์ ์ํด ์ ์
</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;
Tweet.js
import React from 'react';
import { dummyTweets } from '../static/dummyData';
import './Tweets.css';
// ! ์ ์ฝ๋๋ ์์ ํ์ง ์์ต๋๋ค.
// TODO - import๋ฌธ์ ์ด์ฉํ์ฌ Footer ์ปดํฌ๋ํธ๋ฅผ ๋ถ๋ฌ์ค์ธ์.
import Footer from '../Footer';
const Tweets = () => {
return (
<div>
<div className="tweetForm__container">
<div className="tweetForm__wrapper">
<div className="tweetForm__input">
<div className="tweetForm__inputWrapper">
<div className="tweetForm__count" role="status">
<span className="tweetForm__count__text">
{'total: ' + dummyTweets.length}
</span>
</div>
</div>
</div>
</div>
</div>
<ul className="tweets">
{dummyTweets.map((tweet) => {
return (
<li className="tweet" key={tweet.id}>
<div className="tweet__profile">
<img src={tweet.picture} />
</div>
<div className="tweet__content">
<div className="tweet__userInfo">
<span className="tweet__username">{tweet.username}</span>
<span className="tweet__createdAt">{tweet.createdAt}</span>
</div>
<div className="tweet__message">{tweet.content}</div>
</div>
</li>
)
})}
</ul>
{/* TODO - Footer ์ปดํฌ๋ํธ๋ฅผ ์์ฑํฉ๋๋ค. */}
<Footer />
</div>
);
};
export default Tweets;
MyPage.js
import React from "react";
import { dummyTweets } from "../static/dummyData";
import "./MyPage.css";
// ! ์ ์ฝ๋๋ ์์ ํ์ง ์์ต๋๋ค.
// TODO - import๋ฌธ์ ์ด์ฉํ์ฌ Footer ์ปดํฌ๋ํธ๋ฅผ ๋ถ๋ฌ์ต๋๋ค.
import Footer from "../Footer";
const MyPage = () => {
// TODO - filter ๋ฉ์๋๋ฅผ ์ด์ฉํ์ฌ username์ด kimcoding์ธ ์์๋ง ์๋ ๋ฐฐ์ด์ filteredTweet์ ํ ๋นํฉ๋๋ค.
const filteredTweets = dummyTweets.filter( (tweet) =>
tweet.username === "kimcoding"); // ๊ณ ์ฐจํจ์ filter๋ฅผ ์ฌ์ฉํ์ฌ ์ ์
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">
{/* TODO : dummyTweets์ค kimcoding ์ด ์์ฑํ ํธ์ ๋ฉ์ธ์ง๋ง ์์ด์ผ ํฉ๋๋ค. */}
{filteredTweets.map((tweet) => { // ์์ ์ ์๋ filteredTweets๋ฅผ map ํจ์๋ก ์ฌ์ฉํ์ฌ ๋ณด์ฌ์ค๋ค
return (
<li className="tweet" id={tweet.id} key={tweet.id}> // ์ ์๋ fliterํจ์์ ๊ฐ์ ๋ฃ๋๋ค
<div className="tweet__profile">
<img src={tweet.profile} /> // ์ ์๋ fliterํจ์์ ๊ฐ์ ๋ฃ๋๋ค
</div>
<div className="tweet__content">
<div className="tweet__userInfo">
<span className="tweet__username">{tweet.username}</span> // ์ ์๋ fliterํจ์์ ๊ฐ์ ๋ฃ๋๋ค
<span className="tweet__createdAt">{tweet.createdAt}</span> // ์ ์๋ fliterํจ์์ ๊ฐ์ ๋ฃ๋๋ค
</div>
<div className="tweet__message">{tweet.content}</div> // ์ ์๋ fliterํจ์์ ๊ฐ์ ๋ฃ๋๋ค
</div>
</li>
);
})}
</ul>
TODO : Footer ์ปดํฌ๋ํธ๋ฅผ ์์ฑํฉ๋๋ค.
<Footer />
</section>
);
};
export default MyPage;
์คํํ๋ฉด
๋ฐ์ํ