본문 바로가기

프로그래밍, 개발

리액트로 개발하기 - react-router-dom (setup부터 예제까지)

React Router 공식문서

 

Setup

yarn add react-router-dom

공식문서에서는 npm command로 나와있지만, 나는 yarn 을 사용하고 있기 때문에 위와 같은 커맨드 라인을 터미널에 쳐주었다.

그리고 다시, yarn start.

 

Create a Browser Router

createBrowserRouter 를 통해서, router 를 만들어주고, 진입점인 index.js 파일에 해당 라우터를 설정해준다.

이렇게 해주어야 웹 애플리케이션에서 라우팅이 동작할 수 있게 된다.

 

import React from "react";
import ReactDOM from 'react-dom/client';
import './index.css';
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import App from './App';
import BookDetails from './components/BookDetails';
import Books from './components/Books';

const router = createBrowserRouter([
  {
    path: "/",
    element: <App />
  }
]);

ReactDOM.createRoot(document.getElementById("root")).render(
  <React.StrictMode>
    <RouterProvider router={router} />
  </React.StrictMode>
);

 

 

Handle Error

const router = createBrowserRouter([
  {
    path: "/",
    element: <App />,
    errorElement: <ErrorPage />
  }
]);

ErrorPage 라는 page를 작성한 다음에, 해당 페이지를 error 발생 시 보여주도록 설정해주었다.

 

Nested Routes

예를 들어서, 라우팅을 바꾸어도 페이지 UI 상단에 있는 navbar는 유지하고 싶다, sidebar는 그대로 두고 싶다 이런 경우에 아래와 같이 children 값을 사용해서 nested routes 를 구현할 수 있다.

import React from "react";
import ReactDOM from 'react-dom/client';
import './index.css';
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import App from './App';
import BookDetails from './components/BookDetails';
import Books from './components/Books';

const router = createBrowserRouter([
  {
    path: "/",
    element: <App />,
    errorElement: <ErrorPage />,
    children: [
    {path: '/books', element: <Books />},
    {path: '/books/:id', element: <BookDetails />}
  ]
  },
]);

ReactDOM.createRoot(document.getElementById("root")).render(
  <React.StrictMode>
    <RouterProvider router={router} />
  </React.StrictMode>
);

이 경우에는 중요하게 꼭 설정을 해주어야 하는 것이 있다. 바로 <Outlet /> 설정이다. root route 에게 child routes를 렌더링할 곳을 알려주는 것이다.

코드로는 아래와 같이 하면 된다.

import { Outlet } from "react-router-dom";
import Navbar from "./components/Navbar";

function App() {
  return (
    <>
      <Navbar />
      <Outlet />
    </>
  );
}

export default App;

 

createBrowserRouter

이제 좀 더 자세히 createBrowserRouter 를 보면 이렇게 되어 있다. 인자로 RouteObject를 리스트 형식으로 받고 있다.

// createBrowserRouter
export declare function createBrowserRouter(routes: RouteObject[], opts?: DOMRouterOpts): RemixRouter;

그래서 예를 들어서 위의 내용처럼 nested routes 가 아니라 그냥 new route 를 하나 더 생성하고 싶다! 한다면, 아래 코드처럼 하나 더 만들어주면 된다.

const router = createBrowserRouter([
  {
    path: "/",
    element: <App />,
    errorElement: <ErrorPage />,
  },
  {
    path: "books",
    element: <Books />,
  },
]);

그리고 안에 들어가는 path, element 등과 같이 또 어떤 것들이 더 들어갈 수 있는지는 아래의 IndexRouteObject 에서 정의된 값들을 살펴보면 좋을 것 같다.

// RouteObject
export declare type RouteObject = IndexRouteObject | NonIndexRouteObject;
// IndexRouteObject
export interface IndexRouteObject {
    caseSensitive?: AgnosticIndexRouteObject["caseSensitive"];
    path?: AgnosticIndexRouteObject["path"];
    id?: AgnosticIndexRouteObject["id"];
    loader?: AgnosticIndexRouteObject["loader"];
    action?: AgnosticIndexRouteObject["action"];
    hasErrorBoundary?: AgnosticIndexRouteObject["hasErrorBoundary"];
    shouldRevalidate?: AgnosticIndexRouteObject["shouldRevalidate"];
    handle?: AgnosticIndexRouteObject["handle"];
    index: true;
    children?: undefined;
    element?: React.ReactNode | null;
    errorElement?: React.ReactNode | null;
    Component?: React.ComponentType | null;
    ErrorBoundary?: React.ComponentType | null;
    lazy?: LazyRouteFunction<IndexRouteObject>;
}