가수면
Router 본문
패키지 설치
yarn add react-router-dom
폴더 구성
라우터 설정
Router.js
대문자로 넣었어도 주소는 소문자로도 먹힘
import React from "react";
// 1. react-router-dom을 사용하기 위해서 아래 API들을 import 합니다.
import { BrowserRouter, Route, Routes } from "react-router-dom";
import Home from "../Pages/Home";
import About from "../Pages/About";
import Contact from "../Pages/Contact";
import Works from "../Pages/Works";
// 2. Router 라는 함수를 만들고 아래와 같이 작성합니다.
//BrowserRouter를 Router로 감싸는 이유는,
//SPA의 장점인 브라우저가 깜빡이지 않고 다른 페이지로 이동할 수 있게 만들어줍니다!
const Router = () => {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="About" element={<About />} />
<Route path="Contact" element={<Contact />} />
<Route path="Works" element={<Works />} />
</Routes>
</BrowserRouter>
);
};
export default Router;
App.js
import Router from './Shared/Router';
function App() {
return <Router />;
}
export default App;
페이지 이동 훅
버튼
// src/pages/home.js
import { useNavigate } from "react-router-dom";
const Home = () => {
const navigate = useNavigate();
return (
<button
onClick={() => {
navigate("/works");
}}
>
works로 이동
</button>
);
};
export default Home;
링크
<Link to="/contact"> => 절대 경로로 이동 (/주소)
<Link to="contact"> => 상대 경로로 이동 (주소 뒤 +)
import { Link, useLocation } from "react-router-dom";
const Works = () => {
const location = useLocation();
console.log("location :>> ", location);
return (
<div>
<div>{`현재 페이지 : ${location.pathname.slice(1)}`}</div>
<Link to="/contact">contact 페이지로 이동하기</Link>
</div>
);
};
export default Works;
페이지 정보 확인 훅
// src/pages/works.js
import { useLocation } from "react-router-dom";
const Works = () => {
const location = useLocation();
console.log("location :>> ", location);
return (
<div>
<button>버튼</button>
</div>
);
};
export default Works;
레이아웃 양식
Layout.js을 아래 같이 작성해준 뒤 Router.js의 태그들을 Layout 태그로 감싸주기
// src/shared/Layout.js
import React from 'react';
const HeaderStyles = {
width: '100%',
background: 'black',
height: '50px',
display: 'flex',
alignItems: 'center',
paddingLeft: '20px',
color: 'white',
fontWeight: '600',
};
const FooterStyles = {
width: '100%',
height: '50px',
display: 'flex',
background: 'black',
color: 'white',
alignItems: 'center',
justifyContent: 'center',
fontSize: '12px',
};
const layoutStyles = {
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
minHeight: '90vh',
}
function Header() {
return (
<div style={{ ...HeaderStyles }}>
<span>Sparta Coding Club - Let's learn React</span>
</div>
);
}
function Footer() {
return (
<div style={{ ...FooterStyles }}>
<span>copyright @SCC</span>
</div>
);
}
function Layout({ children }) {
return (
<div>
<Header />
<div style={{ ...layoutStyles }}>
{children}
</div>
<Footer />
</div>
);
}
export default Layout;
Dynamic Route
Router.js
<Route path="works" element={<Works />} />
<Route path="works/:id" element={<Works />} />
useParams 훅
path에 있는 아이디값을 조회할 수 있게 해주는 훅
상세 페이지(works.jsx -> work.jsx) 형태
// src/pages/Work.js
import React from "react";
import { useParams } from "react-router-dom";
const data = [
{ id: 1, todo: "리액트 배우기" },
{ id: 2, todo: "노드 배우기" },
{ id: 3, todo: "자바스크립트 배우기" },
{ id: 4, todo: "파이어 베이스 배우기" },
{ id: 5, todo: "넥스트 배우기" },
{ id: 6, todo: "HTTP 프로토콜 배우기" },
];
function Work() {
const param = useParams();
const work = data.find((work) => work.id === parseInt(param.id));
return <div>{work.todo}</div>;
}
export default Work;
v6 바뀐 형식
index파일
APP -> Root
Outlet가 children같은 역할을 해줌 (Root뿐만이 아니라 children이 상대 경로로 붙는 페이지마다 넣어주면 됨)
user.tsx에 자식이 있다면 Outlet이 사용됨
import React from "react";
import { Link, Outlet } from "react-router-dom";
const User = () => {
return (
<div>
<h1>유저</h1>
<Link to="followers">팔로워</Link>
<Outlet /> //Outlet 위치에 따라 Followers컴포넌트 내용 렌더링 위치가 달라짐
</div>
);
};
export default User;
Router
에러 핸들링
useOutletContext
자식 페이지들에 데이터 보내기
import React from "react";
import { Link, Outlet, useParams } from "react-router-dom";
import { users } from "../../components/db";
const User = () => {
const { userId } = useParams();
return (
<div>
<h1>
User with id {userId} is named: {users[Number(userId) - 1].name}
</h1>
<Link to="followers">팔로워</Link>
<Outlet
context={{
nameOfUser: users[Number(userId) - 1].name,
}}
/>
</div>
);
};
export default User;
데이터 받기
import React from "react";
import { useOutletContext } from "react-router-dom";
interface IFollowersContext {
nameOfMyUser: string;
}
const Followers = () => {
const { nameOfMyUser } = useOutletContext<IFollowersContext>();
return <div>여기는 {nameOfMyUser}의 팔로워</div>;
};
export default Followers;
예시 1)
헤더에서 가져온 데이터를 useOutletContext를 통해 Root에서 뿌려주면 모든 페이지에 데이터를 내려줄 수 있음
예시 2)
함수 내려주기
const Root = () => {
const [isDark, setIsDark] = useState(false);
const toggleDark = () => setIsDark((isDark) => !isDark);
return (
<div>
<ThemeProvider theme={isDark ? darkTheme : lightTheme}>
<GlobalStyle />
<Outlet context={{toggleDark}} />
</ThemeProvider>
</div>
);
};
함수 내려받기
interface ICoinsProps {
toggleDark: () => void;
}
const Coins = () => {
const { toggleDark } = useOutletContext<ICoinsProps>();
.
.
.
<button onClick={toggleDark}>토글 모드</button>
Link를 이용해 데이터 내려주기
데이터 보내기 (state 활용)
<CoinsList>
{coins.map((coin) => (
<Coin key={coin.id}>
<Link to={`/${coin.id}`} state={coin.name}>
<Img src={`https://cryptocurrencyliveprices.com/img/${coin.id}.png`} />
{coin.name} →
</Link>
</Coin>
))}
</CoinsList>
데이터 받기
useLocation()사용
useSearchParams
const [readSearchParams, setSearchParams] = useSearchParams();
console.log(readSearchParams); //URLSearchParams {}
URLSearchParams(자바스크립트 내장 메소드)를 이용해 많은 것들을 할 수 있음. 자세한 내용은 아래 참조
https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams
예시)
readSearchParams.has("users") => window.location.pathname === "users" 와 같은 기능
setSearchParams()에 setTimeout을 섞어 url을 조작할 수도 있음
현재 URL의 query string을 읽고 수정하는데 유용함.
const keyword = new URLSearchParams(location.search).get("keyword");
console.log(keyword);
useMatch()
유저가 해당 페이지에 있는지 없는지 확인할 수 있음
const priceMatch = useMatch("/:coinID/price");
console.log(priceMatch);
'React > 라이브러리' 카테고리의 다른 글
[Styled Components] Styled Components Global Style (0) | 2022.12.17 |
---|---|
[Redux] Redux ToolKit thunk (0) | 2022.12.10 |
[Redux] Redux ToolKit (0) | 2022.12.09 |
[Styled Components] Styled Components (0) | 2022.12.02 |
[Redux] Redux (0) | 2022.12.02 |