Routing(라우팅)이란?
URL에 따라 다른 페이지(콘텐츠)를 보여주는 것을 의미한다.
리액트에는 URL을 감시하고 그에 맞는 콘텐츠를 가져오는 라우팅 기능이 내장되어 있지 않기 때문에 react-router-dom 패키지를 설치한다.
npm install react-router-dom
Route 정의하기
지원하려는 URL과 다양한 경로에 대해 어떤 컴포넌트가 로딩되어야 하는지 정의해야 한다.
createBrowserRouter
함수의 인수로 route 정의 객체로 된 배열을 넣어준다.
import { createBrowserRouter } from 'react-router-dom';
const router = createBrowswerRouter([
{
path: '/',
element: <RootLayout />,
errorElement: <ErrorPage />,
children:[
{
path: ''
element: <HomePage />
}
],
}
]);
route 정의 객체의 프로퍼티로는
- path: route가 활성화되어야 하는 경로
- element: 해당 route가 활성화되면 로딩되어야 하는 컴포넌트 (JSX코드)
- children : 중첩 라우팅을 위해 route 객체들로 이루어진 배열을 넣을 수 있다.
- errorElement: 해당 route에 대해 오류가 발생하면 보여주는 에러 페이지를 렌더링할 수 있다.
등이 있다.
인덱스 라우트
위의 예에서 HomePage는 부모 라우트에 있는 경로와 동일한 경로에 로딩되고 있다.
path: ''처럼 빈 경로를 추가하는 대신 index 프로퍼티를 추가하고 그 값을 true로 설정해줄 수 있다.
그러면 그 라우트는 인덱스 라우트로 변하는데, 이것은 부모 라우트가 활성 상태라면 표시되어야 하는 기본 라우트라는 의미이다.
{ index: true, element: <HomePage /> }
createRoutesFromElements
import { createRoutesFromElements, Route, createBrowserRouter } from 'react-router-dom';
const routeDefinitions = createRoutesFromElements(
<Route>
<Route path='/' element={<HomePage />} />
<Route path='/products' element={<ProductsPage />} />
</Route>
);
const router = createBrowserRouter(routeDefinitions);
js 객체가 아닌 createRoutesFromElements 함수에 JSX 코드를 작성해 route 정의를 직접 작성할 수도 있다.
만든 route 정의를 createBroswerRouter에 넣어주면 된다.
RouterProvider
createBrowserRouter로 생성한 모든 router 객체를 Provider 컴포넌트의 router 프로퍼티에 넣어줘야 한다.
import { RouterProvider } from 'react-router-dom';
function App() {
return <RouterProvider router={router} />;
}
router를 활성화하고, router는 URL을 확인한 다음 현재 활성화된 경로에 맞는 컴포넌트를 렌더링한다.
모든 route를 감싸는 레이아웃 만들기
네비게이션 바 같은 경우 여러 페이지에 있을 수 있다. 각 페이지마다 네비게이션 바 컴포넌트를 추가할 수 있지만 페이지 수가 많아지면 번거롭기 때문에 다른 라우트들을 감싸게 만들면 된다.
즉, 최상위 라우트에 레이아웃을 두고, children 프로퍼티에 다른 라우트들을 정의하면 된다.
import { Outlet } from 'react-router-dom';
import MainNavigation from '../components/MainNavigation';
const RootLayout = () => {
return (
<>
<MainNavigation />
<main>
<Outlet />
</main>
</>
);
};
export default RootLayout;
Outlet 컴포넌트는 자식 route 요소들이 렌더링되어야 할 장소를 표시하는 역할을 한다.
페이지들 간 이동하기
Link
만약 페이지들 간에 이동을 한다면 <a href="/products"> 형식으로 a tag를 사용할 수 있지만 링크를 클릭하게 되면 새로고침이 된다.
웹사이트에 HTTP 요청을 보내기 때문인데 그러면 모든 js 코드를 다시 로딩하고 리액트 애플리케이션을 재시작하게 되어 불필요한 작업이 일어난다.
react-router-dom에서 지원하는 Link 컴포넌트는 앵커 태그를 렌더링하게 되지만 새로운 HTTP 요청을 전송하는 기본 설정을 막고 그 대신에 라우트 정의를 확인해 그에 맞춰 콘텐츠를 로딩할 수 있게 해준다.
import { Link } from 'react-router-dom';
<Link to="/products">the list of products</Link>
NavLink
Link과 같은 역할을 하지만 네비게이션 바에서 현재 어떤 링크가 활성 상태인지 알 수 있게 도와주어 링크에 스타일을 넣어줄 수 있다.
<li>
<NavLink
to='/'
className={({ isActive }) =>
isActive ? classes.active : undefined
}
end
>
Home
</NavLink>
</li>
className 프로퍼티에 함수를 넣을 수 있는데, 이 함수는 자동으로 객체를 받고, isActive 프로퍼티를 할당받아 링크가 활성 상태인지 아닌지 판별해 스타일링을 할 수 있다.
NavLink는 실제로 현재 활성인 라우트의 경로가 NavLink의 to에 넣은 경로로 시작하는지 확인하기 때문에 링크에 설정된 경로로 시작하면 활성인 것으로 간주한다.
따라서 '/' 와 '/products'에 해당하는 NavLink가 있으면 /products에 있을 때도 '/'가 활성인 것으로 간주된다.
이럴땐 end 프로퍼티를 설정해 현재 활성인 라우트의 url이 to에 넣은 경로로 끝나면 해당 링크만을 활성으로 간주할 수 있다.
useNavigate
링크로 페이지들 간 이동할 수도 있지만, 링크를 클릭해 이동하지 않고서 예를 들어 폼을 제출한 뒤나, 타이머가 만료되었을 때 다른 페이지로 이동하고 싶을 수 있다.
그럴 땐 useNavigate 훅을 사용하면 된다.
const navigate = useNaviate();
const navigateHandler = () => {
navigate('/');
}
navigate 함수에 경로를 전달해 호출하면 다른 라우트로 전환할 수 있다.
동적 라우트 정의, useParams
만약 어떤 아이템의 상세 페이지를 보여주고 싶을 때 같은 페이지를 사용하지만 페이지마다 해당 아이템에 맞는 데이터를 보여줄 수 있다.
이렇게 다양한 아이템에 대해 다른 경로를 넣을 때 동적 경로를 만들 수 있다.
{ path: '/products/:productId', element: <ProductDetailPage /> }
라우트를 정의할 때 동적인 라우트를 정의할 수 있는데, : 을 넣고 뒤에 원하는 식별자를 넣어서 동적 파라미터를 만든다.
해당 페이지에서 /:productId 대신, url에 사용된 실제 값을 가져오기 위해 useParams 훅을 사용한다.
// ProductDetail.js
const params = useParams();
console.log(params.productId);
useParams를 호출하면 라우트 정의에서 정의한 모든 동적 경로 세그먼트가 담긴 params 객체를 준다.
라우트 정의에서 productId를 동적 경로에 대한 식별자로 정의했기 때문에 접근할 때는 params.productId 로 접근한다.
'React' 카테고리의 다른 글
[React] React Router - action, 데이터 전송하기 (0) | 2023.09.26 |
---|---|
[React] React Router - loader, useLoaderData로 데이터 가져오기 (0) | 2023.09.26 |
[React] Redux에서 비동기 작업하기 (0) | 2023.09.22 |
[React] Redux Toolkit (0) | 2023.09.22 |
[React] 리액트에서 리덕스 사용하기 (0) | 2023.09.21 |