React Router
React Router 설치
- 해당 React 폴더 경로에서
npm install react-router-dom
설치
BrowserRouter, Routes, Route
BrowserRouter
: 브라우저의 URL의 라우팅을 관리하며, React Component를 연결Routes
: 브라우저의 path경로와 매칭되는 모든 자식 Route Component를 관리Route
: path의 경로가 일치한다면 element의 해당하는 Component의 UI로 렌더링
BrowserRouter 와 HashRouter
BrowserRouter
:- 페이지를 라우팅할 때 URL에 실제로는 html파일이 없지만 존재하는 것처럼 폴더를 이동
- 읽기 쉽고 직관적인 URL을 제공
- ex)
http://example.com/route
HashRouter
:- URL주소에
#
(fragment identifier)을 넣어 컨텐츠 안에서의 특정한 위치를 표현 - 브라우저에 호환성 문제가 거의 없으며, 서버 환경에도 문제가 발생하지 않는다.
- 정적 웹사이트를 개발할 때 유용하다.
- ex)
http://example.com/#/route
- URL주소에
Route 구현
import { BrowserRouter, Routes, Route } from "react-router-dom";
import React from "react";
function Practice() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Index />} />
<Route path="/one" element={<One />} />
<Route path="/two" element={<Two />} />
</Routes>
</BrowserRouter>
);
}
function Index() {
return <h1>Hello JJamVa</h1>;
}
function One() {
return <h1>1. See you again</h1>;
}
function Two() {
return <h1>2. GoodBye</h1>;
}
export default Practice;
주소: http://localhost:3001/
주소: http://localhost:3001/one
주소: http://localhost:3001/two
위 코드에 대한 결과 이미지이다.
<Route path="/" element={<Index />} />
<Route path="/one" element={<One />} />
<Route path="/two" element={<Two />} />
첫 Route Component의 path가 '/'
의 의미는 처음 React 프로그램을 실행시켰을 때,
Index Component화면을 호출하여 렌더링 시킨다.
두번째, 세번째 Route Component의 Path는 초기 주소창에서 /one
또는 /two
를 추가적으로 입력하였을 때,
호출되는 Component의 화면을 렌더링한 것이다.
Route를 통해 props를 전달
Route
에 사용되는 Component에 props를 전달하여 사용
import { BrowserRouter, Routes, Route } from "react-router-dom";
import React from "react";
function Practice() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Index />} />
<Route path="/one" element={<One name="JJamVa" />} />
<Route path="/two" element={<Two greeting="JJamHa" />} />
</Routes>
</BrowserRouter>
);
}
function Index() {
return <h1>Hello JJamVa</h1>;
}
function One(props) {
return <h1>1. See you again {props.name}</h1>;
}
function Two(props) {
return <h1>2. GoodBye {props.greeting}</h1>;
}
export default Practice;
주소: http://localhost:3001/
주소: http://localhost:3001/one
주소: http://localhost:3001/two
동작방식은 같지만 Component의 props만 전달하면 된다.
Link
- 클릭하면 애플리케이션 내에서 새로운 경로로 이동하는 링크를 생성하는 Component
- 주소만 바꿀뿐, 페이지를 새로 불러오진 않는다.
- Link를 객체로 넣어줄 경우 필요한 속성
pathname
: 이동할 경로를 나타내는 문자열search
: 쿼리스트링을 나타내는 문자열hash
: URL의 해시를 나타내는 문자열state
: 이동할 경로와 함께 전달할 상태 정보
<Link to="/search?sort=name&sorting=asc" />
<Link
to={{
pathname: "/search",
search: "?sort=name&sorting=asc",
hash: "#the-hash",
state: { fromDashboard: true }
}}
/>
Link 예제
import { BrowserRouter, Routes, Route, Link } from "react-router-dom";
import React from "react";
function Practice() {
return (
<BrowserRouter>
<Link to="/">메인 화면</Link>
<br />
<Link to="/one">1번 화면</Link>
<br />
<Link to="/two">2번 화면</Link>
<Routes>
<Route path="/" element={<Index />} />
<Route path="/one" element={<One name="JJamVa" />} />
<Route path="/two" element={<Two greeting="JJamHa" />} />
</Routes>
</BrowserRouter>
);
}
function Index() {
return <h1>Hello JJamVa</h1>;
}
function JJamVa(props) {
return <h1>1. See you again {props.name}</h1>;
}
function JJamHa(props) {
return <h1>2. GoodBye {props.greeting}</h1>;
}
export default Practice;
파라미터 설정 라우팅
- 동적 라우팅을 위해 사용되는 URL 패턴
import { BrowserRouter, Routes, Route, useLocation } from "react-router-dom";
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Index />} />
<Route path="/blog/:id" element={<Blog />} />
</Routes>
</BrowserRouter>
);
}
function Index() {
return <h1>메인 화면입니다.</h1>;
}
function Blog() {
const location = useLocation();
console.log(location);
let number = location.pathname.split("/")[2];
return <h1>blog의 {number} 입니다.</h1>;
}
export default App;
useLocation()
/blog/10
을 방문했 을 때의 화면이다.
Blog Component 내부를 보았을 때, useLocation()
이 있다.
**useLocation()**은 현재 페이지의 URL 경로, 검색 쿼리, 해시 등의 정보를 객체로 담고 있는 react-router-dom의 커스텀 훅이다.
useLocation에 대한 출력 결과물이다.
number라는 변수를 통해 useLocation의 속성값을 이용하여 출력하였다.
useParams()
function Blog() {
console.log(useParams());
let { id } = useParams();
return <h1>blog의 {id} 입니다.</h1>;
}
Blog Component를 useParams()를 이용하여 출력하여도 똑같이 출력이 가능하다.
**useParams()**는 react-router-dom에서 제공하는 커스텀 훅으로서 동적 라우팅에서 URL 파라미터를 추출할 때 사용된다.
즉, blog/:id
에서 :id
에 따라 useParams()가 담고 있는 정보가 달라진다.
useParams()도 객체 형태이며, 내부에 id라는 속성을 가지고 있는 것을 확인할 수 있다.
Nested Routing
- 중첩된 라우팅 구조를 만들 때 사용되는 개념
- 페이지나 Component 간의 계층 구조를 생성
import {
BrowserRouter,
Routes,
Route,
Link,
useLocation,
Outlet,
} from "react-router-dom";
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Index />} />
<Route path="/menu/" element={<Outlet />}>
<Route path="" element={<Menumain />} />
<Route path="list/" element={<List />} />
<Route path="info/" element={<Info />} />
</Route>
</Routes>
</BrowserRouter>
);
}
function Index() {
return <h1>메인 화면</h1>;
}
function Menumain() {
const location = useLocation();
return <h1>MenuMain: 내경로는 "{location.pathname}" 입니다.</h1>;
}
function List() {
const location = useLocation();
return <h1>List: 내경로는 "{location.pathname}" 입니다.</h1>;
}
function Info() {
const location = useLocation();
return <h1>Info: 내경로는 "{location.pathname}" 입니다.</h1>;
}
export default App;
주소: http://localhost:3001/menu
주소: http://localhost:3001/menu/list
주소: http://localhost:3001/menu/Info
위 이미지는 각 경로에 들어갔을 때, 나오는 화면이다.
<Route path="/menu/" element={<Outlet />}>
<Route path="" element={<Menumain />} />
<Route path="/list/" element={<List />} />
<Route path="/info/" element={<Info />} />
</Route>
Outlet Component는 react-router-dom에서 만들어진 커스텀 훅이다.
이는 중첩된 라우팅을 처리하는데 사용이 된다.
즉, 코드상에서는 '/menu/'경로에 대한 하위 라우팅을 처리한다.
그럼 /menu/
경로에 접근 시, Outlet Component가 렌더링이 된다.
이를 통해 중첩된 라우팅을 처리하는데 사용되며 하위 경로에 대해 렌더링 작업을 해준다.
/menu/경로
방식으로 경로 값을 입력하게 되면
Outlet 내부에 있는 하위 라우터들의 path값이 일치하였을 때, element 작성된 Component를 렌더링 한다.
이를 통해 URL에 대해 구조적으로 표현 및 분리가 가능하다.
이 작업을 **Nested Routing(중첩 라우팅)**이 라 한다.
와일드카드(*)
import { BrowserRouter, Routes, Route } from "react-router-dom";
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/*" element={<Index />} />
<Route path="/hello" element={<Hello />} />
</Routes>
</BrowserRouter>
);
}
function Index() {
return <h1>메인 화면</h1>;
}
function Hello() {
return <h1>Hello World</h1>;
}
export default App;
http://localhost:3001/
http://localhost:3001/hello
http://localhost:3001/bye
*(와일드카드)
는 동적으로 경로를 처리하기 위해 사용한다.
/bye
를 입력하였을 경우, path값과 일치하지 않는다.
<Route path="/*" element={<Index />} />
/*
에 서 *
를 통하여 경로 이후에 어떤 값이든 동적으로 경로를 처리하여 Index Component를 렌더링한 것이다.
다만 경로가 path값과 일치한 경우, 일치한 path에 대한 element값의 Component를 렌더링한다.
useNavigate()
- react-router-dom에서 만들어진 커스텀 훅
- 라우팅 관련 작업을 수행할 때 사용하는 함수
- 함수 컴포넌트 내에서 라우팅을 다룰 때 유용하게 활용
import React from "react";
import { BrowserRouter, Route, Routes, useNavigate } from "react-router-dom";
function Home() {
const navigate = useNavigate();
return (
<div>
<h1>Home Page</h1>
<button onClick={() => navigate("/about")}>About 페이지</button>
</div>
);
}
function About() {
const navigate = useNavigate();
return (
<div>
<h1>About Page</h1>
<button onClick={() => navigate(-1)}>홈</button>
<button onClick={() => navigate("/Link")}>Link 페이지</button>
</div>
);
}
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
</BrowserRouter>
);
}
export default App;
http://localhost:3000/
http://localhost:3000/about
초기 화면은 Home Component를 렌더링하고 있다.
Home Component에서 useNavigate를 이용하여 버튼을 클릭 시, 현재 경로에서 /about
경로로 이동한다.
Route에 /about
경로에 대한 Component 호출이 있기 때문에, 경로를 이동 후 About Component를 렌더링한다.
About Component에는 홈
버튼과 Link페이지
버튼이 있다.
홈버튼을 클릭 시, 초기 화면으로 돌아온다.
홈버튼의 onClick={() => navigate(-1)}
의 기능은 이전 페이지로 돌아가는 기능이다.
navigate안 변수를 작성하면 현재 경로에서 얼만큼 이동할지 경로를 설정할 수 있다.
음수일 경우, 현재 페이지에서 뒤로 n번이동.
양수일 경우, 현재 페이지에서 앞으로 n번이동. 단, 페이지를 앞으로 갔는 기록이 있을 경우 동작한다.
Link버튼을 클릭 시, 아무 화면도 렌더링이 되지 않는다.
하지만 주소창을 확인 해보면 http://localhost:3000/Link
인 것을 확인할 수 있다.
Routes안 path에 /link
에 대한 정보가 없기 때문에 빈화면이 출력된다.