본문 바로가기

STUDY/React

React | 서브라우트 Nested Route

레이아웃을 유지하는건 다루지 않음..
(사실 저것도 서브라우트다..)

react-router-dom install

타입스크립트를 사용할 경우에는 타입 정보가 들어있는 @types가 붙은 패키지도 다운로드 해야 함

$ npm install react-router-dom @types/react-router-dom

라우트 설정

src경로에 routes폴더를 생성하고, index.tsx파일을 생성한다.
이 파일이 App.tsx(App.js/App.jsx)를 대신해 루트 역할을 할 것이다.
(컴포넌트에는 그냥 H1태그로 글씨만 나타나도록 구성했으므로 생략)

// src/routes/index.tsx

import React from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom';

import Layout from '../components/Layout';
import Dashboard from '../pages/Dashboard';
import Cash from '../pages/cash';
import Page2 from '../pages/Page2';

const Root: React.FC = () => {
  return (
    <BrowserRouter>
       <Layout>
         <Switch>
           <Route path="/" exact component={Dashboard} />
           <Route path="/cash" component={Cash} />
           <Route path="/page-2" component={Page2} />
         </Switch>
       </Layout>
    </BrowserRouter>
  );
};

export default Root;
  • <BrowserRouter> : HTML5의 히스토리 API를 사용하게 해줌
  • <Switch> : 로케이션과 매치되는 첫 번째 <Route> 혹은 <Redirect>를 렌더해준다
  • <Route> : 라우트 컴포넌트는 path와 매치되는 컴포넌트를 렌더해주는 역할

Root컴포넌트 등록

App컴포넌트 대신 등록한다.

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';

import Root from './routes';
import reportWebVitals from './reportWebVitals';

ReactDOM.render(
  <React.StrictMode>
    <Root />
  </React.StrictMode>,
  document.getElementById('root')
);

서브라우트 설정

캐시 관리 메뉴에서 "일별 관리"와 "월별 관리"는 아예 다른 페이지로 두고, "추가"와 "상세"페이지는 캐시 관리 페이지 내에서 바뀌도록..
일단 일별 관리, 월별 관리는 아까와 동일하게 index.tsx에 등록한다.
순서가 중요하다. /cash가 가장 마지막에 위치해야 한다.

<Route path="/cash/daily" component={Daily} />
<Route path="/cash/monthly" component={Monthly} />
<Route path="/cash" component={Cash} />

이렇게 등록하면 일별 관리, 월별 관리 메뉴를 클릭하면 해당 컴포넌트가 렌더된다.
캐시 관리 메뉴에서 어떤 항목들은 유지하면서 다른 서브 페이지를 렌더하기 위해 서브라우트를 만들것이다.

 

먼저 /routes경로에 /cash폴더를 생성한 후, index.tsx파일을 생성한다.
그리고 서브라우트들을 작성하면 된다. 지금은 /charge/detail같은 경로만 추가했지만
실제로는 /:id이런식으로 파라미터를 받아 상세 페이지를 출력할 수 있다.

// src/routes/cash/index.tsx

import React from 'react';
import {
  Switch,
  RouteComponentProps,
  Route,
  withRouter,
} from 'react-router-dom';

import Charge from '../../pages/cash/Charge';
import Detail from '../../pages/cash/Detail';

const CashRouter: React.FC<RouteComponentProps> = (props) => {
  const { match } = props;

  return (
    <Switch>
      <Route path={`${match.url}/charge`} exact component={Charge} />
      <Route path={`${match.url}/detail`} exact component={Detail} />
    </Switch>
  );
};

export default withRouter(CashRouter);

 

그리고 나서 /pages/cash/index.tsx에 위에서 만든 CashRouter를 추가한다.

// src/pages/cash/index.tsx

import React from 'react';
import { RouteComponentProps, Link } from 'react-router-dom';
import CashRouter from '../../routes/cash';

const Cash: React.FC<RouteComponentProps> = ({
  match,
}: RouteComponentProps) => {
  return (
    <div>
      <h1>
        /pages/cash/index{' '}
        <Link to={`${match.url}/charge`} role="button">
          <button>추가</button>
        </Link>{' '}
        <Link to={`${match.url}/detail`} role="button">
          <button>상세</button>
        </Link>
      </h1>

      <CashRouter />
    </div>
  );
};

export default Cash;

이렇게 하면 캐시 관리 페이지의 /pages/cash/index는 유지되면서, 아래의 추가, 상세 페이지가 다르게 렌더된다.
관리자 페이지나 마이 페이지(내 정보)같은 서브 메뉴가 많은 페이지를 만들 때 유용할 것 같다.

 

대충 동작한다는 뜻..