⚠️ 이 포스팅은 codevolution을 공부하고 정리한 블로그 포스팅입니다. ⚠️
포스팅에 해당하는 목차는 다음과 같습니다:
React Router 라이브러리란?
react-router는 특정한 주소와 컴포넌트를 연결시켜 주소 이동으로 다른 컴포넌트 화면을 보여줄 수 있도록 하는 라이브러리다.
1. react-router-dom 라이브러리 v6 설치하기
v6 다운받기
yarn add react-router-dom@6
가장 최신버전 다운받기
yarn add react-router-dom@latest
2. index.js에 BrowserRouter 적용하기
<BrowserRouter>로 프로젝트에 라우터를 적용한다. <BrowserRouter> 컴포넌트는 1) 사용자가 입력한 주소를 감지하는 역할 2) 여러 종류의 라우터 컴포넌트를 제공 3) 웹 애플리케이션에 HTML5의 History API를 사용하여 페이지를 새로고침하지 않고도 주소를 변경할 수 있게 함 4) 현재 주소에 관련된 정보를 props 로 쉽게 조회하거나 사용할 수 있도록 해준다.
<BrowserRouter> 컴포넌트 내부에 있는 컴포넌트는 라우터 기능을 사용할 수 있게 된다. 아래 예제에서는 가장 최상위 컴포넌트인 App을 <BrowserRouter>로 감싸줘서 App의 자식 컴포넌트에서도 라우터 기능을 적용시켰다. 특정 컴포넌트에만 라우터 기능을 부여하고 싶다면 라우터 기능을 부여하고 싶은 컴포넌트에만 <BrowserRouter> 컴포넌트로 감싸주면 된다.
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { BrowserRouter } from 'react-router-dom';
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('root')
);
reportWebVitals();
1) BrowserRouter가 너무 길다고 느껴지면 as를 사용해 별명을 지정해주자
아래의 코드에서는 BrowserRouter를 사용하기 위해 별명으로 지정한 Router를 대신 사용했다.
import { BrowserRouter as Router } from 'react-router-dom';
ReactDOM.render(
<Router>
<App />
</Router>,
document.getElementById('root')
);
2) ReactDOM.render() 코드
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
ReactDOM.render(첫번째 파라미터, 두번째 파라미터)
- 첫번째 파라미터: 무엇을 렌더시킬까 → 최상위 컴포넌트 <App>
- 두번째 파라미터: 어디에 렌더시킬까 → id가 root인 element 즉 public > index.html에 있는 id가 root인 요소
3. 폴더 구조 만들기
라우터로 등록한 컴포넌트를 일반 컴포넌트와 구분하기 위해 다른 폴더에 넣는것이 일반적이다. 폴더 이름은 일반적으로 pages 또는 routes를 사용한다.
또는 아래와 같이 폴더를 컴포넌트 이름으로 사용할 수도 있다.
4. 세부화면 만들기
Home.js
import React from 'react';
const Home = () => {
return <div>Home Page</div>;
};
export default Home;
About.js
import React from 'react';
const About = () => {
return <div>About Page</div>;
};
export default About;
5. App.js에서 Route 적용하기
1) Routes, Route 컴포넌트 사용법
<Routes>
<Route path="/" element={<컴포넌트이름 />}></Route> // 첫번째 컴포넌트는 루트 경로
<Route path="/경로이름" element={<컴포넌트이름 />}></Route>
<Route path="경로이름" element={<컴포넌트이름 />}></Route> // 슬래시 기호(/) 생략 가능
</Routes>
Routes
- Route 컴포넌트를 감싸주는 부모 컴포넌트
- 주소 변경을 감지하고 일치하는 Route 를 찾아서 표시해주는 역할
- Route가 하나일때도 반드시 Routes 컴포넌트로 감싸주어야 한다
Route
- 브라우저 주소창에 있는 주소와 path안에 있는 주소가 같을 경우 element 안에 들어 있는 컴포넌트를 보여준다
- 가장 첫번째 Route 컴포넌트는 path가 루트(/)여야 한다
2) Route 컴포넌트 적용하는 순서
1) react-router-dom에서 Routes와 Route import하기
2) Routes로 Route 컴포넌트 감싸주기
4) Route 컴포넌트의 props로 path에는 브라우저 경로 element에는 불러올 컴포넌트 이름을 전달해준다
3) 예시
App.js
import { Routes, Route } from 'react-router-dom';
import About from './components/About';
import Home from './components/Home';
function App() {
return (
<>
<Routes>
<Route path="/" element={<Home />}></Route>
<Route path="/about" element={<About />}></Route>
</Routes>
</>
);
}
export default App;
브라우저 & 콘솔창
브라우저 주소에 도메인을 입력하면 Home 컴포넌트가 출력되고 /about을 입력하면 About 컴포넌트가 출력된다
6. <Link> 컴포넌트 사용해서 페이지 이동하기
사용자가 페이지를 이동하기 위해 브라우저의 주소를 외워 주소창에 입력하는 일은 비효율적이다. <Link> 컴포넌트를 사용해 해당 컴포넌트로 이동할 수 있는 링크를 생성할 수 있다. 브라우저에 컴파일된 HTML에서는 Link 컴포넌트가 a태그로 변환된다.
리액트 라우터에서 a 태그를 사용해 페이지를 이동하면 페이지를 처음부터 다시 새로 불러오기 때문에 사용할 수 없다. 대신 a 태그와 비슷한 역할을 하는 Link 컴포넌트를 사용해 페이지를 이동시켜준다. Link 컴포넌트를 사용해 페이지를 이동하면 애플리케이션은 그대로 유지한 상태에서 HTML5 History API를 사용해 페이지의 주소만 변경해준다. 즉 Link 컴포넌트에는 페이지 전환을 방지하는 기능이 내장되어 있어 기존 상태를 유지할 수 있다.
1) Link 컴포넌트 사용법
<Link to="연결하고 싶은 경로">메뉴 이름</Link>
2) 예시
Navbar.js
import React from 'react';
import { Link } from 'react-router-dom';
const Navbar = () => {
return (
<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
</nav>
);
};
export default Navbar;
브라우저 & 콘솔창
7. <NavLink> 컴포넌트로 active한 링크 파악하기
NavLink 컴포넌트는 Link 컴포넌트처럼 페이지를 이동시켜주는 컴포넌트다. Link 컴포넌트와 다른점은 NavLink 컴포넌트는 링크가 현재 라우터일경우 active 클래스를 받는다. 일반적으로 메뉴가 active할때 다른 스타일링을 준다. NavLink 컴포넌트가 현재 라우터에 자동으로 active 클래스를 부여하므로 이를 이용해서 다른 스타일을 줄 수 있다.
- Link 컴포넌트의 확장 버전
- 현재 활성화된 라우터의 스타일을 적용하기 위한 컴포넌트
- to에 지정된 path와 URL이 매칭되는 경우 class="active"를 가지며 새로운 스타일을 적용할 수 있음
1) 예제
NavLink.js
import React from 'react';
import { NavLink } from 'react-router-dom';
const Navbar = () => {
return (
<nav>
<NavLink to="/">Home</NavLink>
<NavLink to="/about">About</NavLink>
</nav>
);
};
export default Navbar;
브라우저 & 콘솔창
브라우저 주소가 /about 이므로 현재 라우터 /about을 가지고 있는 NavLink 컴포넌트에 class="active"가 들어가 있다.
2) CSS로 active 클래스를 가지고 있는 요소에 다른 스타일 주기
index.css
nav a.active {
text-decoration: none;
font-weight: bold;
}
3) prop으로 active 클래스를 가지고 있는 요소에 다른 스타일 주기
NavLink 컴포넌트에는 isActive라는 Boolean 프로퍼티를 가지고 있다. 현재 라우터일때는 true 값을 가지고 현재 라우터가 아닐때는 false값을 가진다. 이를 이용해 현재 라우터일때 부여하고 싶은 스타일을 아래의 예제와 같이 만들어 줄 수 있다.
Navbar.js
import React from 'react';
import { NavLink } from 'react-router-dom';
const Navbar = () => {
const navLinkStyles = ({ isActive }) => {
return {
fontWeight: isActive ? 'bold' : 'normal',
textDecoration: isActive ? 'none' : 'underline',
};
};
return (
<nav>
<NavLink to="/" style={navLinkStyles}>
Home
</NavLink>
<NavLink to="/about" style={navLinkStyles}>About</NavLink>
</nav>
);
};
export default Navbar;
브라우저 & 콘솔창
현재 라우터일때 새로운 스타일 속성이 들어가 있다.
8. useNavigate로 자유롭게 페이지 이동하고 뒤로가기 버튼 만들기
useNavigate는 Link 컴포넌트를 사용하지 않고 다른 페이지로 이동을 해야 하는 상황에 사용하는 Hook이다.
1) useNavigate 적용하는 순서
1) useNavigate라는 Hook을 import한다
2) 쉽게 사용하기 위해 변수 navigate에 useNavigate의 리턴값을 할당한다
3) 변수 navigate안에 이동하고 싶은 주소를 인자로 넣어주면 navigate 함수가 실행될때 해당 주소로 이동한다
2) 예시
OrderSummary.js
import React from 'react';
const OrderSummary = () => {
return <div>Order Summary</div>;
};
export default OrderSummary;
App.js
import { Routes, Route } from 'react-router-dom';
import About from './components/About';
import Home from './components/Home';
import Navbar from './components/Navbar';
import OrderSummary from './OrderSummary';
function App() {
return (
<>
<Navbar />
<Routes>
<Route path="/" element={<Home />}></Route>
<Route path="/about" element={<About />}></Route>
<Route path="order-summary" element={<OrderSummary />}></Route>
</Routes>
</>
);
}
export default App;
Home.js
import React from 'react';
import { useNavigate } from 'react-router-dom';
const Home = () => {
const navigate = useNavigate();
return (
<>
<div>Home Page</div>
<button onClick={() => navigate('order-summary')}>Place Order</button>
</>
);
};
export default Home;
3) replace 옵션으로 현재 페이지를 기록에 남기지 않기
replace 옵션을 사용하면 페이지를 이동할 때 현재 페이지를 페이지 기록에 남기지 않는다. 즉 다른 페이지에서 뒤로가기 버튼을 눌러도 replace: true 옵션을 가지고 있는 페이지는 기록이 되지 않기 때문에 그 전 페이지로 이동하게 된다.
Home.js
import React from 'react';
import { useNavigate } from 'react-router-dom';
const Home = () => {
const navigate = useNavigate();
return (
<>
<div>Home Page</div>
<button onClick={() => navigate('order-summary', { replace: true })}>
Place Order
</button>
</>
);
};
export default Home;
4) state 옵션으로 현재 페이지에서 전달하고 싶은 데이터 넘겨주기
state 옵션을 사용하면 이동하는 페이지에 데이터를 넘겨줄 수 있다.
import React from 'react';
import { useNavigate } from 'react-router-dom';
const Home = () => {
const navigate = useNavigate();
return (
<>
<div>Home Page</div>
<button onClick={() => navigate('order-summary', { state: { order-status: true } })}>
Place Order
</button>
</>
);
};
export default Home;
넘겨진 데이터는 useLocation으로 접근 할 수 있다. (아래의 9. useLocation()으로 현재 URL 정보 가져오기 설명 참조 )
const location = useLocation()
console.log(location.state)
5) 뒤로가기 버튼 만들기
useNavigate를 사용해서 페이지 뒤로 가기 또는 앞으로 가기를 구현할 수 있다. navigate 함수를 사용할 때 파라미터가 숫자 타입이라면 앞으로 가거나, 뒤로 간다. 예를 들어 navigate(-1) 을 하면 한 번 뒤로 가고 navigate(-2) 를 하면 두 번 뒤로 간다. 뒤로가기를 한번 한 상태에서 navigate(1)은 앞으로 한 번 페이지가 이동한다.
OrderSummary.js
import React from 'react';
import { useNavigate } from 'react-router-dom';
const OrderSummary = () => {
const navigate = useNavigate();
return (
<>
<div>Order Confirmed</div>
<button onClick={() => navigate(-1)}>Go Back</button>
</>
);
};
export default OrderSummary;
9. useLocation()으로 현재 URL 정보 가져오기
1) pathname과 search
import React, { useEffect } from 'react'
import { useLocation } from 'react-router-dom'
const About = () => {
const location = useLocation()
useEffect(() => {
console.log(location)
}, [location])
return <>Hello World</>
}
export default About
url이 /about일때 Posts 컴포넌트를 보여준다면 location 정보를 콘솔창에 출력했을때 아래와 같이 나온다.
url이 /about?filter=something일때 location 정보를 콘솔창에 출력했을때 아래와 같이 나온다.
2) state
특정 url에 전달하고싶은 state(데이터)가 있다면 아래와 같이 작성한다.
import React, { useEffect } from 'react'
import { Link, useLocation } from 'react-router-dom'
const About = () => {
const location = useLocation()
useEffect(() => {
console.log(location)
}, [location])
return (
<>
<Link to={'/about/contact'} state={{ email: 'maple@gmail.com' }}>
Contact
</Link>
</>
)
}
export default About
Contact 링크를 클릭하면 /about/contact으로 이동하며 state값으로 이메일 주소를 받는다.
10. Not Found 페이지 구현하기
브라우저에 라우터로 등록되지 않은 주소를 입력하면 콘솔창에 No routes matched location... 이라는 경고 메세지가 나온다.
사용자가 잘못된 URL을 입력했을때 Page Not Found 페이지를 불러오는 것이 일반적이다. 라우터에 등록되지 않은 모든 URL을 입력했을때 PageNotFound 컴포넌트를 불러오기 위해 path에 *를 전달해준다. *는 라우터의 등록된 path 주소 이외의 모든 주소를 의미한다.
App.js
import { Routes, Route } from 'react-router-dom';
import About from './components/About';
import Home from './components/Home';
import Navbar from './components/Navbar';
import PageNotFound from './components/PageNotFound';
import OrderSummary from './OrderSummary';
function App() {
return (
<>
<Navbar />
<Routes>
<Route path="/" element={<Home />}></Route>
<Route path="/about" element={<About />}></Route>
<Route path="order-summary" element={<OrderSummary />}></Route>
<Route path="*" element={<PageNotFound />}></Route>
</Routes>
</>
);
}
export default App;
11. 중첩 Route (서브 Route)
어떤 컴포넌트의 하위 메뉴에서 또 다른 컴포넌트를 보여주고 싶을때 Route를 중첩시켜 부모 자식 관계로 만들어준다. 부모 Route 컴포넌트의 path를 자식 Route 컴포넌트의 path에 자동으로 포함시키기 때문에 그 뒤에 올 주소만 적어주면 된다. 예를 들어 부모 Route 컴포넌트의 path가 products라면 자식 Route 컴포넌트의 path는 prdocuts로 시작한다.
- 도메인/products: Products 컴포넌트 출력
- 도메인/products/featured: FeaturedProducts 컴포넌트 출력
- 도메인/products/new: NewProducts 컴포넌트 출력
<Route path="products" element={<Products />}>
<Route path="featured" element={<FeaturedProducts />}></Route>
<Route path="new" element={<NewProducts />}></Route>
</Route>
중첩 Route 적용하는 순서
1) 부모 컴포넌트와 자식 컴포넌트 생성하기
2) 부모 컴포넌트를 가지고 있는 Route로 자식 컴포넌트를 가지고 있는 Route를 감싼다
3) 이때 자식 컴포넌트를 가지고 있는 Route의 path에서는 부모 컴포넌트의 path를 자동으로 포함하므로 그 뒤에 사용할 주소만 입력한다
4) 부모 컴포넌트에서 Outlet이라는 컴포넌트를 불러와 부모 Route의 자식으로 들어가는 컴포넌트를 출력해준다
Products.js
- 부모 컴포넌트 생성하기
- Link로 하위 컴포넌트 주소 연결해주기
- Outlet이라는 컴포넌트를 불러와 부모 Route의 자식으로 들어가는 JSX 엘리먼트 보여주기 (FeaturedProducts, NewProducts의 내용이 보여주기 위해 사용한다)
import React from 'react';
import { Link } from 'react-router-dom';
const Products = () => {
return (
<>
<div>
<input type="search" placeholder="Search Products" />
</div>
<nav>
<Link to="featured">Featured</Link>
<Link to="new">New</Link>
</nav>
</>
);
};
export default Products;
FeaturedProducts.js
Products의 하위 컴포넌트로 사용할 자식 컴포넌트 생성하기
import React from 'react';
const FeaturedProducts = () => {
return <div>List of Featured Products</div>;
};
export default FeaturedProducts;
NewProducts.js
Products의 하위 컴포넌트로 사용할 자식 컴포넌트 생성하기
import React from 'react';
const NewProducts = () => {
return <div>List of New Products</div>;
};
export default NewProducts;
App.js
products 페이지에서만 보여주고 싶은 컴포넌트를 products를 가지고 있는 Route의 children으로 넣어준다
import { Routes, Route } from 'react-router-dom';
import About from './components/About';
import FeaturedProducts from './components/FeaturedProducts';
import Home from './components/Home';
import Navbar from './components/Navbar';
import NewProducts from './components/NewProducts';
import PageNotFound from './components/PageNotFound';
import Products from './components/Products';
import OrderSummary from './OrderSummary';
function App() {
return (
<>
<Navbar />
<Routes>
<Route path="/" element={<Home />}></Route>
<Route path="/about" element={<About />}></Route>
<Route path="order-summary" element={<OrderSummary />}></Route>
<Route path="products" element={<Products />}>
<Route path="featured" element={<FeaturedProducts />}></Route>
<Route path="new" element={<NewProducts />}></Route>
</Route>
<Route path="*" element={<PageNotFound />}></Route>
</Routes>
</>
);
}
export default App;
결과창
중첩 컴포넌트에서 params와 index 적용해주기
<Routes>
<Route path="posts" element={<Posts />}>
<Route index element={<PostIndex />} />
<Route path=":postId" element={<PostDetail />} />
</Route>
</Routes>
/posts → Post 컴포넌트 출력 & PostIndex 컴포넌트 출력
/posts/123 → Post 컴포넌트 출력 & PostDetail 컴포넌트 출력
12. index props으로 상위 라우터와 같은 경로 사용하기
현재 브라우저 URL에 보여지는 컴포넌트는 다음과 같다:
- /products: Products 컴포넌트
- /products/featured: FeaturedProducts 컴포넌트
- /products/new: NewProducts 컴포넌트
Products 컴포넌트를 가지고 있는 라우트의 서브 라우트 중 하나를 /products 경로에 보여주고 싶을때는 props으로 path 대신 index를 사용하면 된다. index props 는 path="/"와 동일한 의미를 가진다.
App.js
<Route index element={<FeaturedProducts />}></Route>는 props으로 index를 가지고 있고 path가 없으므로 부모 라우트에서 해당 컴포넌트가 보여진다.
import { Routes, Route } from 'react-router-dom';
import About from './components/About';
import FeaturedProducts from './components/FeaturedProducts';
import Home from './components/Home';
import Navbar from './components/Navbar';
import NewProducts from './components/NewProducts';
import PageNotFound from './components/PageNotFound';
import Products from './components/Products';
import OrderSummary from './OrderSummary';
function App() {
return (
<>
<Navbar />
<Routes>
<Route path="/" element={<Home />}></Route>
<Route path="/about" element={<About />}></Route>
<Route path="order-summary" element={<OrderSummary />}></Route>
<Route path="products" element={<Products />}>
<Route index element={<FeaturedProducts />}></Route>
<Route path="featured" element={<FeaturedProducts />}></Route>
<Route path="new" element={<NewProducts />}></Route>
</Route>
<Route path="*" element={<PageNotFound />}></Route>
</Routes>
</>
);
}
export default App;
13. path 주소창에 URL 파라미터 사용하기 (동적 라우팅 적용)
users/1, users/2, users/3과 같이 user의 아이디값을 받아 상세페이지를 만들고 싶을때는 동적 라우팅을 적용해야 한다.
동적 라우팅 (Dynamic Routing)이란?
페이지 주소를 정의할 때 가끔은 유동적인 값을 전달해야할 때도 있다. 이때 라우터의 경로에 유동적인 값인 URL 파라미터나 쿼리를 넣어서 특정 페이지로 이동하는데 이것을 동적 라우팅이라고 한다.
1) URL 파라미터
- 특정 아이디, 이름을 사용하여 조회할 때 사용
domain/profile/maple
2) 쿼리 (쿼리 스트링)
- 주소의 뒷부분에 ? 문자열 이후에 key=value 로 값을 정의하며 & 로 구분을 하는 형태
- 어떤 키워드를 검색할때나 페이지에 필요한 옵션을 전달할 때 사용
domain/about?page=1&keyword=react
path에 URL 파라미터 주기
Route의 path에 :userId라는 파라미터를 넣어주면 userId에 들어가는 값은 동적으로 바뀐다. 즉 주소창에 domain/users/1로도 UserDetail 컴포넌트에 접근할 수 있고 domain/users/hello이라는 주소로도 UserDetail 컴포넌트에 접근할 수 있다는 의미다.
<Route path="users" element={<Users />}>
<Route path=":userId" element={<UserDetail />}></Route>
<Route path="admin" element={<Admin />}></Route>
</Route>
Users.js
user 상세페이지의 부모 컴포넌트인 Users 컴포넌트르 만들고 user1, 2, 3을 보여준다.
import React from 'react';
import { Outlet } from 'react-router-dom';
const Users = () => {
return (
<>
<div>User 1</div>
<div>User 2</div>
<div>User 3</div>
<Outlet />
</>
);
};
export default Users;
UserDetail.js
users/1, users/2, users/3과 같이 user의 아이디값을 받아 표시해줄 상세페이지 컴포넌트를 만든다.
import React from 'react';
const UserDetail = () => {
return <div>User Detail</div>;
};
export default UserDetail;
App.js
- users: User 컴포넌트
- users/:userId: UserDetail 컴포넌트
users/ 뒤에 어떤 값이 오면 그것을 userId로 받고 UserDetail 컴포넌트를 출력한다. 예) URL이 users/1이면 1이 userId가 되며 URL이 users/admin이면 admin이 userId가 된다.
import { Routes, Route } from 'react-router-dom';
import About from './components/About';
import FeaturedProducts from './components/FeaturedProducts';
import Home from './components/Home';
import Navbar from './components/Navbar';
import NewProducts from './components/NewProducts';
import PageNotFound from './components/PageNotFound';
import Products from './components/Products';
import UserDetail from './components/UserDetail';
import Users from './components/Users';
import OrderSummary from './OrderSummary';
function App() {
return (
<>
<Navbar />
<Routes>
<Route path="/" element={<Home />}></Route>
<Route path="/about" element={<About />}></Route>
<Route path="order-summary" element={<OrderSummary />}></Route>
<Route path="products" element={<Products />}>
<Route index element={<FeaturedProducts />}></Route>
<Route path="featured" element={<FeaturedProducts />}></Route>
<Route path="new" element={<NewProducts />}></Route>
</Route>
<Route path="users" element={<Users />}>
<Route path=":userId" element={<UserDetail />}></Route>
</Route>
<Route path="*" element={<PageNotFound />}></Route>
</Routes>
</>
);
}
export default App;
Admin.js
users/admin으로 접근했을때 표시할 Admin 컴포넌트 생성하기.
import React from 'react';
const Admin = () => {
return <div>Admin</div>;
};
export default Admin;
App.js
Admin.js를 보여줄 수 있는 라우트를 추가한 App 컴포넌트. 앞으로 users/admin은 Admin 컴포넌트를 불러오고 그 이외의 모든 users/주소는 UserDetail 컴포넌트를 불러온다.
import { Routes, Route } from 'react-router-dom';
import About from './components/About';
import Admin from './components/Admin';
import FeaturedProducts from './components/FeaturedProducts';
import Home from './components/Home';
import Navbar from './components/Navbar';
import NewProducts from './components/NewProducts';
import PageNotFound from './components/PageNotFound';
import Products from './components/Products';
import UserDetail from './components/UserDetail';
import Users from './components/Users';
import OrderSummary from './OrderSummary';
function App() {
return (
<>
<Navbar />
<Routes>
<Route path="/" element={<Home />}></Route>
<Route path="/about" element={<About />}></Route>
<Route path="order-summary" element={<OrderSummary />}></Route>
<Route path="products" element={<Products />}>
<Route index element={<FeaturedProducts />}></Route>
<Route path="featured" element={<FeaturedProducts />}></Route>
<Route path="new" element={<NewProducts />}></Route>
</Route>
<Route path="users" element={<Users />}>
<Route path=":userId" element={<UserDetail />}></Route>
<Route path="admin" element={<Admin />}></Route>
</Route>
<Route path="*" element={<PageNotFound />}></Route>
</Routes>
</>
);
}
export default App;
Users.js
Users 컴포넌트를 가지고 있는 Route에 하위 Route가 있다. 부모 Route 컴포넌트 안에 Outlet이라는 컴포넌트를 불러와 부모 Route의 자식으로 들어가는 JSX 엘리먼트를 보여준다.
import React from 'react';
import { Outlet } from 'react-router-dom';
const Users = () => {
return (
<>
<div>User 1</div>
<div>User 2</div>
<div>User 3</div>
<Outlet />
</>
);
};
export default Users;
14. useParams 훅 사용해서 URL 파라미터 접근하기
users/:userId로 접근하면 UserDetail 컴포넌트가 출력된다. UserDetail 컴포넌트에 userId값을 불러와 출력하고 싶다면 URL 파라미터에 접근하기 위해 useParams라는 훅을 사용해야 한다.
UserDetail.js
useParams 훅은 객체 형태로 URL 파라미터의 이름과 값을 받아온다. users/1을 주소창에 입력했을때 userId는 1이므로 params를 콘솔창에 출력했을때 객체형태로 { userId: '1' }이 출력된다.
import React from 'react';
import { useParams } from 'react-router-dom';
const UserDetail = () => {
const params = useParams();
console.log(params);
return <div>Details about User</div>;
};
export default UserDetail;
콘솔창
UserDetail.js
params.userId로 URL 파라미터에 접근한다.
import React from 'react';
import { useParams } from 'react-router-dom';
const UserDetail = () => {
const params = useParams();
console.log(params.userId);
return <div>Details about User {params.userId}</div>;
};
export default UserDetail;
구조분해할당 문법을 적용해 객체에서 userId를 바로 꺼내올 수도 있다.
import React from 'react';
import { useParams } from 'react-router-dom';
const UserDetail = () => {
const { userId } = useParams();
console.log(userId);
return <div>Details about User {userId}</div>;
};
export default UserDetail;
콘솔창
URL 파라미터를 받아와 Details about User 문구 뒤에 출력해준다.
13. useSearchParams 훅 사용해서 쿼리 스트링 적용하기 (동적 라우팅 적용)
guests?filter=active와 같이 key=value 받아 주소창에 표시해주고 싶을때는 동적 라우팅을 적용해야 한다.
동적 라우팅 (Dynamic Routing)이란?
페이지 주소를 정의할 때 가끔은 유동적인 값을 전달해야할 때도 있다. 이때 라우터의 경로에 유동적인 값인 URL 파라미터나 쿼리를 넣어서 특정 페이지로 이동하는데 이것을 동적 라우팅이라고 한다.
1) URL 파라미터
- 특정 아이디, 이름을 사용하여 조회할 때 사용
domain/profile/maple
2) 쿼리 (쿼리 스트링)
- 주소의 뒷부분에 ? 문자열 이후에 key=value 로 값을 정의하며 & 로 구분을 하는 형태
- 어떤 키워드를 검색할때
- 페이지에 필요한 옵션을 전달할 때
domain/about?page=1&keyword=react
Guests.js
useSearchParams 훅은 useState 훅처럼 배열이 반환된다. 반환된 배열안에 있는 첫번째 원소는 searchParams, 두번째 원소는 setSearchParams다.
- searchParams: 쿼리 스트링을 지정
- setSearchParams: 지정된 쿼리 스트링을 가져옴
import React from 'react';
import { Outlet, useSearchParams } from 'react-router-dom';
const Guests = () => {
const [searchParams, setSearchParams] = useSearchParams();
// searchParams의 get 메서드로 filter가 active인 상태를 가져온다
const showActiveGuests = searchParams.get('filter') === 'active';
return (
<>
<div>Guest 1</div>
<div>Guest 2</div>
<div>Guest 3</div>
<Outlet />
<div>
// 버튼을 클릭하면 ?filter=active가 URL에 추가된다
<button onClick={() => setSearchParams({ filter: 'active' })}>
Active Guests
</button>
// 버튼을 클릭하면 URL에 있던 기존 쿼리 스트링을 삭제한다
<button onClick={() => setSearchParams({})}>Reset Filter</button>
</div>
// 주소창에 ?filter=active이 있으면 첫번째 문구를 출력하고 없다면 두번째 문구를 출력한다
{showActiveGuests ? (
<div>Showing active guests</div>
) : (
<div>Showing all guests</div>
)}
</>
);
};
export default Guests;
댓글