React - Router ์‚ฌ์šฉ

TH_velogยท2023๋…„ 11์›” 28์ผ
0

React

๋ชฉ๋ก ๋ณด๊ธฐ
13/16
post-thumbnail

๐Ÿ“Œ Router

๐Ÿ“– Routing

  • ์‚ฌ์šฉ์ž๊ฐ€ ์š”์ฒญํ•œ url์— ์•Œ๋งž์€ ํŽ˜์ด์ง€๋ฅผ ์ƒˆ๋กœ๊ณ ์นจ ์—†์ด ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ณด์—ฌ์ค€๋‹ค.
  • ๋ฆฌ์•กํŠธ ์ž์ฒด์— ๊ธฐ๋Šฅ์ด ๋‚ด์žฅ๋˜์–ด ์žˆ์ง€ ์•Š์•„ ์„ค์น˜๋ฅผ ์ง„ํ–‰.
  • react-router ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

๐Ÿ“— React-router-dom

npm install react-router-dom 
or
npm install react-router-dom@6 // 6๋ฒ„์ „ - ํŠน์ • ๋ฒ„์ „ ์„ค์น˜

โœ… package.json ํŒŒ์ผ ํ™•์ธ


๐Ÿ“˜ BrowserRouter

  • ๋ธŒ๋ผ์šฐ์ €์˜ ์ฃผ์†Œ ํ‘œ์‹œ์ค„์— ํ˜„์žฌ ์œ„์น˜๋ฅผ ์ €์žฅํ•˜๊ณ  ๋ธŒ๋ผ์šฐ์ €์— ๋‚ด์žฅ๋œ ๊ธฐ๋ก ์Šคํƒ์„ ์‚ฌ์šฉํ•˜์—ฌ ํƒ์ƒ‰.
  • history api๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
  • ๋ผ์šฐํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ ์ตœ ์ƒ์œ„์— BrowserRouter ์ปดํฌ๋„ŒํŠธ๋กœ Router๋ฅผ ๊ฐ์‹ธ์ค€๋‹ค.
  • ์ตœ์ƒ๋‹จ์— ์œ„์น˜ํ•œ๋‹ค.

โœ…src/index ํŒŒ์ผ

โœ”๏ธ import { BrowserRouter } from "react-router-dom";
โœ”๏ธ ์ตœ์ƒ์œ„ indexํŒŒ์ผ์—์„œ BrowserRouter ์ปดํฌ๋„ŒํŠธ๋กœ App์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐ์‹ผ๋‹ค.


๐Ÿ“˜ Routes, Route

๐Ÿ“ Routes
  • import {Routes} from 'react-router-dom';
  • Route ์ƒ์œ„ ๊ฒฝ๋กœ์— ์กด์žฌ.
๐Ÿ“ Route
  • import {Route} from 'react-router-dom';
  • path์— ๋”ฐ๋ผ ํ•ด๋‹น ์ง€์ •๋œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋ง
  • path์— URL ๊ฒฝ๋กœ ์ž‘์„ฑ
  • element์— ์ปดํฌ๋„ŒํŠธ ์ž‘์„ฑ

โœ”๏ธ Path์— ์ž…๋ ฅํ•œ ๊ฒฝ๋กœ์™€ ๋งž์„ ๊ฒฝ์šฐ element ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ณด์—ฌ์ฃผ์„ธ์š” ๋ผ๊ณ  ์ƒ๊ฐ์„ ํ•˜๋ฉด ๋!
EX)

<Route path="/about" element={<About />}>

url ๐Ÿ‘‰ http://localhost:3000/about
๋ณด์—ฌ์ง€๋Š” ์ปดํฌ๋„ŒํŠธ ๐Ÿ‘‰ About ์ปดํฌ๋„ŒํŠธ


๐Ÿ“— Router ์‚ฌ์šฉ ๊ธฐ์กด - BrowserRouter

// App.js
import {Routes, Route} from 'react-router-dom';
import RouterMain from './components/router/RouterMain';
import RouterAbout from './components/router/RouterAbout';
import RouterPage from './components/router/RouterPage';

function App() {
  return (
    <div className="App">
      <Routes>
        <Route path="/" element={ <RouterMain /> }/> 
        <Route path="/about" element={ <RouterAbout />} />
        <Route path="/page" element={ <RouterPage />} />
      </Routes>
    </div>
  );
}
export default App;
- - - - - - - - - - - - - - - - - -
๐Ÿ‘‡ url ์ž…๋ ฅ ์‹œ 
http://localhost:3000 ๐Ÿ‘‰ RouterMain ์ปดํฌ๋„ŒํŠธ ๋…ธ์ถœ 
http://localhost:3000/about ๐Ÿ‘‰ RouterAbout ๋…ธ์ถœ
http://localhost:3000/page ๐Ÿ‘‰ RouterPage ๋…ธ์ถœ

์ •์ƒ์ ์œผ๋กœ url์— ๋งž๊ฒŒ ๋‚˜์˜ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

โš ๏ธ ์ž˜๋ชป๋œ ๊ฒฝ๋กœ์ผ ๊ฒฝ์šฐ ๊ฒฝ๊ณ ๋ฌธ.
EX) localhost:3000/test

์ž˜๋ชป๋œ ๊ฒฝ๋กœ์ผ ๊ฒฝ์šฐ ์•ˆ๋‚ด๋ฅผ ํ•ด์ฃผ๋Š” ์ปดํฌ๋„ŒํŠธ๋„ ํ•„์š”!
// path="*" RouterError ์ปดํฌ๋„ŒํŠธ
<Route path="*" element={ <RouterError /> }/> {/* ์—†๋Š” ๊ฒฝ๋กœ */}

โœ”๏ธ path="*" ์ž˜๋ชป๋œ url์˜ ๊ฒฝ์šฐ Error ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ณด์—ฌ์ง€๋„๋ก ์™„๋ฃŒ!


๐Ÿ“Link

  • ํŽ˜์ด์ง€ ์ด๋™ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ.
  • to={url ๊ฒฝ๋กœ ์ž…๋ ฅ}
  • a ํƒœ๊ทธ๋กœ ์ƒ์„ฑ

โœ…EX)

import {Routes, Route, Link} from 'react-router-dom';
import RouterMain from './components/router/RouterMain';
import RouterAbout from './components/router/RouterAbout';
import RouterPage from './components/router/RouterPage';
import RouterError from './components/router/RouterError';

function App() {
  return (
    <div className="App">
      {/* ๐Ÿ‘‡ ๋งํฌ */}
      <div className="link">
        <Link to={"/"} >Main</Link>
        <Link to={"/about"} >about</Link>
        <Link to={"/page"} >page</Link>
      </div>
      <Routes>
        <Route path="/" element={ <RouterMain /> }/>
        <Route path="/about" element={ <RouterAbout />} />
        <Route path="/page" element={ <RouterPage />} />
        <Route path="*" element={ <RouterError /> }/> {/* ์—†๋Š” ๊ฒฝ๋กœ */}
      </Routes>
    </div>
  );
}

๐Ÿ‘‡ link aํƒœ๊ทธ ํด๋ฆญ ์‹œ url์— ๋งž๋Š” ์ปดํฌ๋„ŒํŠธ๋กœ ๋ฐ”๋€Œ๊ณ  ์žˆ๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค!


๐Ÿ“useNavigate
  • ํŠน์ • ์ด๋ฒคํŠธ ๋ฐœ์ƒ ์‹œ ์‹คํ–‰ํ•˜๋„๋ก ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋‹ค๋ฅธ ํ•จ์ˆ˜ ์‹คํ–‰ ํ›„ ์กฐ๊ฑด์— ๋”ฐ๋ผ ์‹คํ–‰ ๊ฐ€๋Šฅ
  • aํƒœ๊ทธ ์™ธ buttonํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉ ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋’ค๋กœ ๊ฐ€๊ธฐ ์‚ฌ์šฉ.
import {Routes, Route, useNavigate} from 'react-router-dom';

const navigate = useNavigate(); // ๐Ÿ‘ˆ
return (
  <div className="App">
    {/* ๋งํฌ */}
    <div className="link">
      <button type="button" onClick={()=> navigate("/") }>Main</button>
      <button type="button" onClick={()=> navigate("/about")}>about</button>
      <button type="button" onClick={()=> navigate("/page")}>page</button>
    </div>
    <Routes>
      <Route path="/" element={ <RouterMain /> }/>
      <Route path="/about" element={ <RouterAbout />} />
      <Route path="/page" element={ <RouterPage />} />
      <Route path="*" element={ <RouterError /> }/> {/* ์—†๋Š” ๊ฒฝ๋กœ */}
    </Routes>
  </div>
);

โœ”๏ธ ์ •์ƒ์ ์œผ๋กœ ๋™์ž‘ ํ™•์ธ

function aboutClick() {
    navigate("/about")
  }
  
<button type="button" onClick={()=> aboutClick() }>about</button>

โœ”๏ธ ํ•จ์ˆ˜ ๋‚ด์— ์ž…๋ ฅํ•˜์—ฌ ์กฐ๊ฑด์— ๋”ฐ๋ผ ์‹คํ–‰ํ•˜๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

// -1 ๋’ค๋กœ ๊ฐ€๊ธฐ -2๋ฅผ ์ž…๋ ฅํ•ด๋„ ๊ฐ€๋Šฅ - ๊ทธ์ „ ๋‹จ๊ณ„๋กœ ๋Œ์•„๊ฐ„๋‹ค.
navigate(-1)

โœ”๏ธ ๋’ค๋กœ ๊ฐ€๊ธฐ -1


๐Ÿ“˜ nested routes ์ค‘์ฒฉ ๋ผ์šฐํŒ…

  • page/detail ๋“ฑ ์ƒ์„ธํŽ˜์ด์ง€๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ๊ฒฝ์šฐ
  • ๊ฐ™์€ ๋‚ด์šฉ์„ ๋ณด์—ฌ์ฃผ๊ณ  ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ๋งŒ ๋‚ด์šฉ๋งŒ ๊ต์ฒด๋  ๊ฒฝ์šฐ(Tab ๋ฉ”๋‰ด์™€ ๋น„์Šทํ•œ)
  • Route ์ž์‹์œผ๋กœ Route ์ž…๋ ฅ path ๋ถ€๋ชจ /path ์ด์–ด์„œ ์ž‘์„ฑํ•œ๋‹ค๊ณ  ์ƒ๊ฐ(๋ถ€๋ชจ path="/page" ์ž์‹ path="detail" ๐Ÿ‘‰ /page/detail )
// โœ”๏ธ Route ์ž์‹์œผ๋กœ Route๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ๋! 
<Route path="/page" element={ <RouterPage /> } >
  <Route path="detail" element={ <RouterDetail /> } />
</Route>

์ž์‹์œผ๋กœ ๋“ค์–ด๊ฐ„ Route๋Š” path์— /page/ ์ดํ›„์— ์ž…๋ ฅ๋  url์„ ์ž…๋ ฅํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค!
detail๋งŒ ์ž‘์„ฑํ•˜๋ฉด /page/detail ๊ฒฝ๋กœ๊ฐ€ ์ง€์ •๋ฉ๋‹ˆ๋‹ค.

๋ผ์šฐํ„ฐ๋กœ ๊ฒฝ๋กœ, ์ปดํฌ๋„ŒํŠธ ๋“ฑ๋ก์ด ๋๋‚ฌ์Šต๋‹ˆ๋‹ค!
/page/detail ๊ฒฝ๋กœ๋กœ ์ ‘๊ทผํ•  ๊ฒฝ์šฐ ๊ฒฝ๊ณ ๋Š” ๋‚˜์˜ค์ง€ ์•Š๋Š”๋ฐ
detail์˜ ์ •๋ณด๋Š” ๋ณด์—ฌ์ง€์ง€ ์•Š๊ณ  page ์ปดํฌ๋„ŒํŠธ ๋‚ด์šฉ๋งŒ ๋‚˜์˜ค๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

EX)
/page
/page/detail
โœ”๏ธ ๊ฐ™์€ ๋‚ด์šฉ ๋…ธ์ถœ

๊ฒฝ๋กœ๋Š” ๋ฐ”๋€Œ์—ˆ๋Š”๋ฐ ๋ Œ๋”๋ง ๋˜์ง€ ์•Š๋Š” ์ด์œ ๋Š” page ํ•˜์œ„ detail ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์œ„์น˜, ๊ณต๊ฐ„์„ ์žก์•„์ฃผ์ง€ ์•Š์•„์„œ ์ž…๋‹ˆ๋‹ค!

โœ…์ถ”๊ฐ€๋กœ page์— detail๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ์œ„ํ•ด Outlet์„ ์‚ฌ์šฉ!


๐Ÿ“ Outlet
  • import { Outlet } from "react-router-dom";
  • ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ์—์„œ Outlet์‚ฌ์šฉ.
  • outlet ์œ„์น˜์— url - ํ•ด๋‹นํ•˜๋Š” location ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋ง
import { Outlet } from "react-router-dom";
<Outlet />
// Route ๐Ÿ‘‰ /page ํ•˜์œ„๋กœ detail, board ์ถ”๊ฐ€
<Route path="/page" element={ <RouterPage /> } >
 <Route path="detail" element={ <RouterDetail /> } />
 <Route path="board" element={ <RouterBoard /> } />
</Route>

// RouterPage.jsx
<div className="page">
  <h1>RouterPage ์ปดํฌ๋„ŒํŠธ ์ž…๋‹ˆ๋‹ค.</h1>
  <hr />
  {/* ๐Ÿ‘‡ Route page ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ  */}
  <Outlet />
</div>
โœ…๊ฒฐ๊ณผ 
๊ฒฝ๋กœ: /page
/page ์ปดํฌ๋„ŒํŠธ ๋‚ด์šฉ๋งŒ ๋‚˜์˜ค๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
๊ฒฝ๋กœ: /page/detail
page ์ปดํฌ๋„ŒํŠธ ๋‚ด์šฉ ๋ฐ detail ์ปดํฌ๋„ŒํŠธ ๋‚ด์šฉ
๊ฒฝ๋กœ: /page/board
page ์ปดํฌ๋„ŒํŠธ ๋‚ด์šฉ ๋ฐ board ์ปดํฌ๋„ŒํŠธ ๋‚ด์šฉ

๐Ÿ“— Router ์‚ฌ์šฉ v6.4 ์ƒˆ๋กœ์šด - createBrowserRouter

  • React Router v6.4๋ถ€ํ„ฐ ์‚ฌ์šฉ
  • BrowserRouter ๐Ÿ‘‰ RouterProvider ์ตœ์ƒ๋‹จ์—์„œ ๊ฐ์‹ผ๋‹ค
  • RouterProvider์— props๋กœ router= {router} ํ•„์ˆ˜ ์ž…๋ ฅ
  • createBrowserRouter ์ž‘์„ฑ ์‹œ path, element ์ž‘์„ฑํ•˜๋ฉฐ ์ค‘์ฒฉ ๋ผ์šฐํŒ…์€ children์œผ๋กœ ์ž‘์„ฑ

โœ… ๊ธฐ์กด๊ณผ ์ƒˆ๋กœ์šด Router ์ฝ”๋“œ ๋น„๊ต

// Configure nested routes with JSX
createBrowserRouter(
  createRoutesFromElements(
    <Route path="/" element={<Root />}>
      <Route path="contact" element={<Contact />} />
      <Route
        path="dashboard"
        element={<Dashboard />}
        loader={({ request }) =>
          fetch("/api/dashboard.json", {
            signal: request.signal,
          })
        }
      />
      <Route element={<AuthLayout />}>
        <Route
          path="login"
          element={<Login />}
          loader={redirectIfUser}
        />
        <Route path="logout" action={logoutUser} />
      </Route>
    </Route>
  )
);

// โญ Or use plain objects โญ
createBrowserRouter([
  {
    path: "/",
    element: <Root />,
    children: [
      {
        path: "contact",
        element: <Contact />,
      },
      {
        path: "dashboard",
        element: <Dashboard />,
        loader: ({ request }) =>
          fetch("/api/dashboard.json", {
            signal: request.signal,
          }),
      },
      {
        element: <AuthLayout />,
        children: [
          {
            path: "login",
            element: <Login />,
            loader: redirectIfUser,
          },
          {
            path: "logout",
            action: logoutUser,
          },
        ],
      },
    ],
  },
]);
// ์ถœ์ฒ˜ - https://reactrouter.com/en/main/start/overview
๐Ÿ“ RouterProvider

src/index.js

๐Ÿ‘‡๊ธฐ์กด

๐Ÿ‘‡์ƒˆ๋กœ์šด

โœ”๏ธ BrowserRouter ๋Œ€์‹  RouterProvider ์‚ฌ์šฉ.
โœ”๏ธ props๋กœ router={router}๋ฅผ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค
โœ”๏ธ ๊ธฐ์กด Routes Route ๋Œ€์‹  router.jsx ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด ๋ถ„๋ฆฌํ•˜์—ฌ ๊ด€๋ฆฌ๋ฅผ ํ•ฉ๋‹ˆ๋‹ค!

// src/index.js ์ฐธ๊ณ  
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import reportWebVitals from './reportWebVitals';
import { RouterProvider } from 'react-router-dom';
import router from './router/router';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
      <RouterProvider router={router} />
  </React.StrictMode>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

๐Ÿ“ createBrowserRouter

๐Ÿ‘‡๊ธฐ์กด Route

๐Ÿ‘‡ ์ƒˆ๋กœ์šด - object๋กœ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.

//EX)
import { createBrowserRouter } from 'react-router-dom';
const router = createBrowserRouter([
  {
  	path:'/',
    element:'<App />'
  }
export default router;
// router.jsx EX)
import { createBrowserRouter } from 'react-router-dom';

import App from '../App';
import RouterMain from '../components/router/RouterMain';
import RouterAbout from '../components/router/RouterAbout';
import RouterPage from '../components/router/RouterPage';
import RouterDetail from '../components/router/RouterDetail';
import RouterBoard from '../components/router/RouterBoard';

const router = createBrowserRouter([
  {
    path:"/",
    element: <App />,
    children:[
      {
        index: true, // ๐Ÿ‘ˆ App Outlet default ์ปดํฌ๋„ŒํŠธ 
    	// path:"/",  ๐Ÿ‘ˆ path:'/' ์ž…๋ ฅํ•ด๋„ App Outlet ๋ Œ๋”๋ง
        element:<RouterMain />
      },
      {
        path:"about",
        element:<RouterAbout />
      },
      {
        path:"page",
        element:<RouterPage />,
        children: [
          {
            path:"detail",
            element:<RouterDetail />
          },
          {
            path:"board",
            element:<RouterBoard />
          }
        ]
      },
    ]
  },
])
export default router;

โœ… Route ์ž‘์„ฑ์ด ์™„๋ฃŒ๋˜์—ˆ์œผ๋‹ˆ ์ด์ œ App ๊ธฐ์ค€์œผ๋กœ children์„
๋ณด์—ฌ์ฃผ๊ธฐ ์œ„ํ•ด App.js์— Outlet์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค!

// App.js
import './App.scss';
import {useNavigate, Outlet} from 'react-router-dom';
function App() {
  const navigate = useNavigate();
  return (
    <div className="App">
      <div className="link">
        <button type="button" onClick={()=> navigate("/")}>Main</button>
        <button type="button" onClick={()=> navigate("/about")}>about</button>
        <button type="button" onClick={()=> navigate("/page")}>page</button>
        <button type="button" onClick={()=> navigate("/page/detail")}>detail</button>
        <button type="button" onClick={()=> navigate("/page/board")}>board</button>
      </div>
      {/* ๐Ÿ‘‡Outlet ์ถ”๊ฐ€ App-> children */}
      <Outlet />
    </div>
  );
}
export default App;

โœ… ๋

๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๐Ÿ˜

profile
๊ณต๋ถ€&๊ธฐ๋ก

0๊ฐœ์˜ ๋Œ“๊ธ€