[React] react-router 6.4

Seju·2023년 8월 21일
1

React

목록 보기
2/9

router 6.4 version 구성하기


🤙 라우터란?


React-router 공식 문서

  • React RouterReact 기반의 Javascript 라이브러리로써, 웹 애플레케이션 간에 페이지 전환 및 라우팅을 관리하는 역할을 담당한다.
  • React Router를 사용하면 싱글 페이지 애플리케이션 내에서 여러 페이지 개념을 사용할 수 있게된다. 또한 동적 라우팅 기능도 포함하고 있어 URL 매개변수를 사용해 데이터를 전달 및 복잡한 중첩된 라우트들을 관리할 수 있게된다.

🦖 라우터 구성하기


🦋 react-router-dom 설치

$ pnpm i react-router-dom

🏯 라우터 추가하기

  • 라우터를 App.jsxmain.jsx에 구성하거나 routes 파일을 따로 관리하는 경우도 있고 각기 다르지만 나는 파일을 최소단위로 쪼개는걸 지향하기 때문에 routes라는 파일을 생성 후 거기서 관리하는 방법을 선택했다.
📝 routes.jsx

import { createBrowserRouter} from 'react-router-dom';


const router = createBrowserRouter([
  {
    path: '/',
    element: <RootLayout />,
    children: [
      { index: true, element: <Home /> },
      { path: 'products', element: <Product /> },
      { path: 'contact', element: <Contact /> },
    ],
  },
]);

export default router;
  • 위 코드처럼 createBrowserRouter 메서드 내에 배열내의 객체로 설정하는 방법이 현재 최신방법이지만, createRoutesFromElements 내에서 컴포넌트로써 관리하는 방법도 가능하다.

import { createBrowserRouter, createRoutesFromElements } from 'react-router-dom';

const router = createBrowserRouter(
  createRoutesFromElements(
    <Route path="/" element={<RootLayout />}>
      <Route index element={<Home />} />
      <Route path="products" element={<Product />} />
      <Route path="contact" element={<Contact />} />
    </Route>
  )
);

🐬 RouterProvider에 구성한 router 객체 공급하기


  • App.jsx에서 구성했던 router객체를 import해서 RouterProvider 컴포넌트에 공급해준다.

import { RouterProvider } from 'react-router-dom';
import router from './routes';

function App() {
  return (
    <div className="App">
      <RouterProvider router={router} />
    </div>
  );
}

export default App;

  • 일단 RouterProvier로 만든 router를 공급하면, 기본적으로 해당 페이지별로 컴포넌트가 정의 되어있는데, 이제 특정 버튼/태그를 클릭하면 해당 페이지로 이동할 수 있도록 Link 컴포넌트로 감싸주면 된다.

  • 아래는 Navigation 기능에 특화된 NavLink라는 라우터 컴포넌트인데, 해당 NavLinkisActive,isPending이라는 상태를 className에 콜백함수에서 인자로 가질 수 있으며 해당 상태를 기반으로 다양한 스타일링 또는 조건처리가 가능해진다.

<import { NavLink } from 'react-router-dom';

const Nav = () => (
  <nav>
    <ul className="flex gap-4 border-b-2 py-4">
      <li>
        <NavLink
          to="/"
          className={({ isActive }) => {
            return isActive ? 'font-black text-rose-500' : '';
          }}
        >
          Home
        </NavLink>
      </li>
      <li>
        <NavLink
          to="/products"
          className={({ isActive }) => {
            return isActive ? 'font-black text-rose-500' : '';
          }}
        >
          Products
        </NavLink>
      </li>
      <li>
        <NavLink
          to="/contact"
          className={({ isActive }) => {
            return isActive ? 'font-black text-rose-500' : '';
          }}
        >
          Contact
        </NavLink>
      </li>
    </ul>
  </nav>
);

export default Nav;

🐝 자식 컴포넌트가 렌더링 될 수 있는 출구 <Outlet /> 컴포넌트


  • 아래 코드처럼 형제 컴포넌트의 중첩된 라우팅 컴포넌트를 화면에 나타내려면 Outlet 컴포넌트를 사용해야한다.
  • React에서의 props.children과 같은 느낌으로 사용하면 문제없다

📝 routes.jsx

const router = createBrowserRouter([
  {
    path: '/',
    element: <RootLayout />,
    children: [
      { index: true, element: <Home /> },
      { path: 'products', element: <Product /> },
      { path: 'contact', element: <Contact /> },
    ],
  },
]);

export default router;
  • 현재 가장 최상위 컴포넌트 routesRootLayout 컴포넌트일때, 해당 RootLayout 컴포넌트 사이에 <Outlet /> 컴포넌트를 끼워넣으면 RootLayout 내부의 자식 컴포넌트들이 해당 path를 따라 렌더링 될 수 있게된다.

📝 RootLayout.jsx


import { Outlet } from 'react-router-dom';

const RootLayout = () => {
  return (
    <>
      <NavigationBar />
      <main>
    // props.children 대체!
        <Outlet />
      </main>
      <SiteInfo />
    </>
  );
};

🌏 동적 라우팅 구성해보기

  • 경로가 동적으로 변경될 경우에 routespath를 동적으로 설정 가능한데
  • :가 해당 경로를 변수로 받겠다는 느낌으로 생각하면 편할것같다
const router = createBrowserRouter(
  createRoutesFromElements(
    <Route path="/" element={<RootLayout />}>
      <Route index element={<Home />} />
      <Route path="products" element={<Product />} />
      <Route path="product/edit/:productId" element={<ProductEdit />} />
      <Route path="contact" element={<Contact />} />
    </Route>
  )
);
  • path:productId로 설정했을때 해당 path로 이동하는 간단한 예시를 확인해보자.
function Product() {
  useDocumentTitle('제품 목록');
  const { isLoading, data: products } = useProductList();

  if (isLoading) {
    return <Spinner size={160} />;
  }

  return (
    <>
      <div>
        <h1>Products</h1>
        <ul >
          {products &&
            products.items?.map((product) => {
              return (
                <li key={product.id} className="justify-self-center">
                  <Link to={`/product/edit/${product.id}`}>
                    <img
                      src={getPocketBaseImageURL(product,'photo')}
                      alt={product.title}
                      
                    />
                    <figcaption>
                      <span>{product.title}</span>
                      <span>
                        {numberWithComma(product.price)}
                      </span>
                    </figcaption>
                  </Link>
                </li>
              );
            })}
        </ul>
      </div>
    </>
  );
}
  • fetch를 활용한 useProductList로 서버에서 데이터를 가져와 렌더링을 했으며, 해당 productItem들의 id를 기반으로 템플릿 리터럴을 사용해, /product/edit/${product.id}로 이동할 수 있도록 구성하였다.
profile
Talk is cheap. Show me the code.

0개의 댓글