반응형
React 로 HackerRank News WebApp 만들기
전체코드 보러가기
1.hook 브랜치에서 확인하실 수 있습니다.
사용기술
- react- v18
- react-router-dom - v6
실행화면
학습내용
react-router-dom 사용
- App.js
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
<Router>
<ToolBar />
<Routes>
<Route exact path="/" element={<NewsView />} />
<Route path="/news" element={<NewsView />} />
<Route path="/ask" element={<AskView />} />
<Route path="/jobs" element={<JobsView />} />
<Route path="/userInfo/:id" element={<UserInfo />} />
<Route path="/askInfo/:id" element={<AskInfo />} />
</Routes>
</Router>
<Route>
태그를 사용하기 위해서는 위와 같이<Routes>
태그로 감싸줘야합니다.path 에는 이동할 url 주소를 명시하고, element 에는 화면에 렌더링될 컴포넌트를 입력합니다.
ToolBar.js
import { Link } from "react-router-dom";
<Link to="/news" style={{ textDecoration: "none", margin: "0 5px" }}>
News
</Link>
<Link to="/ask" style={{ textDecoration: "none", margin: "0 5px" }}>
Ask
</Link>
<Link to="/jobs" style={{ textDecoration: "none", margin: "0 5px" }}>
Jobs
</Link>
- 클릭해서 해당 페이지로 넘어가고 싶을땐
<Link to="/">
태그를 사용하면 됩니다.
useEffect, useState 사용
- NewsList.js
import React, { useEffect, useState } from "react";
import { fetchNews } from "../../api/index.js";
function NewsList() {
const [newsList, setNewsList] = useState([]);
useEffect(() => {
async function getNewsList() {
// You can await here
const response = await fetchNews();
// ...
setNewsList(response.data);
}
getNewsList();
}, []);
return (
<ul>
{newsList.map((newsItem) => (
<li key={newsItem.id}>
<div>
{newsItem.points || 0}
</div>
<div>
<p>
{newsItem.title}
<span>
{newsItem.domain} {newsItem.user}
</span>
</p>
</div>
</li>
))}
</ul>
);
}
export default NewsList;
- 화면에 렌더링될 newsList 변수를 useState 를 사용해 빈 배열로 먼저 선언했습니다.
- useEffect 를 활용해 화면이 전환되자마자
getNewsList()
함수를 실행시켜 뉴스리스트를 받아왔고,setNewsList()
를 이용해 newsList 상태를 업데이트 했습니다.
조건부 렌더링
- ListItem.js
위의 News 페이지와 Ask, Jobs 페이지는 비슷한 구조를 가지고 있기 때문에 ListItem.js 라는 파일을 생성해 한 파일에서 조건부 렌더링을 통해 3개의 리스트들을 다 출력해주기로 했습니다.
import React, { useEffect, useState } from "react";
import { Link, useLocation } from "react-router-dom";
import { fetchAsk, fetchJobs, fetchNews } from "../../api";
export function ListItem() {
const { pathname } = useLocation();
const [ItemList, setItemList] = useState([]);
const fetchList = async () => {
if (pathname === "/news" || pathname === "/") {
const newsList = await fetchNews();
setItemList(newsList.data);
} else if (pathname === "/ask") {
const askList = await fetchAsk();
setItemList(askList.data);
} else if (pathname === "/jobs") {
const jobsList = await fetchJobs();
setItemList(jobsList.data);
}
};
useEffect(() => {
fetchList();
}, []);
return (
<>
<ul style={{ padding: "0", margin: "0" }}>
{ItemList.map((Item) => (
<linkey={Item.id}>
<div>
{Item.points || 0}
</div>
<div>
<p style={{ margin: "0" }}>
{/* domain 있을 때 */}
{Item.domain && (
<span>
<a href={Item.url}>{Item.title}</a>
<small>{Item.domain}</small>
</span>
)}
{/* domain 없을 때 */}
{!Item.domain && (
<span>
<Link to={{ pathname: `/askInfo/${Item.id}` }}>
{Item.title}
</Link>
<small>
<a href={Item.url}>{Item.domain}</a>
</small>
</span>
)}
{/* user 정보 있으면 표시 */}
{Item.user && (
<small>
{" "}
by{" "}
<Link to={{ pathname: `/userInfo/${Item.user}` }}>
{Item.user}
</Link>
</small>
)}
{/* 작성시간 있으면 표시 */}
{Item.time_ago && <small> {Item.time_ago}</small>}
</p>
</div>
</li>
))}
</ul>
</>
);
}
- react-router-dom 의 useLocation 속성을 이용해 현재 페이지의 url 값을 추출한 뒤, url에 따라 ItemList 변수값에 담기는 정보들이 바뀌도록 했습니다.
- 그리고 각각에 point, domain, user 등의 정보가 없는 경우를 && 연산자를 이용해 다르게 표시하도록 했습니다.
보완해야할 점
- Redux와 Redux-Saga, Recoil 을 학습중에 있습니다.
- 빨리 이 프로젝트에 적용해보고 싶네요..
반응형
'Study > React' 카테고리의 다른 글
Next.js + TypeScript ) 스크롤 내릴 시에 특정 컴포넌트 숨기기 (0) | 2022.07.15 |
---|---|
Next.js ) Input 입력값 태그로 변환하기 (TypeScript) (0) | 2022.07.15 |
React ) redux-saga 기반 api 호출 연습 (1) | 2022.05.11 |
React ) Recoil 로 Axios 비동기 처리하기 (0) | 2022.05.10 |
React ) Class 형 보다 Hook(함수) 형을 권장하는 이유 (0) | 2022.05.06 |
댓글