반응형

리액트 라우터

각각의 url에 따라 선택된 데이터를 하나의 페이지에서 렌더링 해주는 라이브러리
SPA(Single Page Application)에서 새로운 페이지를 로드하지 않고

하나의 페이지 안에서 필요한 컴포넌트만 가져와서 다른 페이지를 나타내는 방식을 지원.

*라우팅 : 사용자가 요청한 url에 따라 해당 url에 맞게 페이지를 보여주는 것
이전 MPA(Multiple Page Application)에서는 새로운 페이지를 로드하며 페이지를 이동하는 방식
<a href="sub.html"> 서브페이지 </a>

 

 

Home v6.6.2

I'm on v5 The migration guide will help you migrate incrementally and keep shipping along the way. Or, do it all in one yolo commit! Either way, we've got you covered to start using the new features right away.

reactrouter.com

 

1) 라우터 설치하기

npm install react-router-dom



2) 라우터 사용하기

1. 상위 컴포넌트에서 라우터를 적용 <BrowserRouter> 컴포넌트
ex>
<BrowserRouter>
            <App></App>
</BrowserRouter>

2. 경로에 따라 보일 component를 설정 <Routes><Route> 컴포넌트
Routes컴포넌트는 여러 Route를 감싸서 그중 url이 일치하는 라우트 단 하나만 렌더링 시켜줌
Route는 path속성에 경로element속성에 컴포넌트를 지정

<Routes>
	<Route path="경로" element={<component /> } /> //path가 일치하면 element에 있는 컴포넌트를 렌더링함
	<Route path="경로" element={<component /> } />
</Routes>

 

예제) 

우선은 주소로 이동했을 때 보여줄 페이지를 만들어 주자 pages폴더를 만들어서 폴더 안에서 관리해 준다.

Home.js

import React from "react";
import { Link } from "react-router-dom";

const Home = () => {
  return (
    <div>
      <h2>홈</h2>
      <p>가장 먼저 보여지는 페이지입니다.</p>
      <Link to="/product">제품페이지</Link>
    </div>
  );
};

export default Home;

Home은 기본주소일 때 보여줄 거 기 때문에 <Router path=' '  element={<Home/>}/>으로

App에  넣어주면 된다.

 

홈에서는 제품페이지로 이동할 수 있는 링크가 있고 링크 주소는 해당주소에서 /product로 이동한다.

 

Product.js

import React from "react";
import { Link } from "react-router-dom";

const Product = () => {
  return (
    <div>
      <h2>제품페이지</h2>
      <p>제품페이지입니다</p>
      <Link to="/">홈</Link>
    </div>
  );
};

export default Product;

Product는 링크를 타고 /product로 이동했을 때 렌더링되도록

<Router path='/product' element={<Product/>}/>으로 App에 넣어 준다.

Product에서 다시 홈으로 돌아갈 수 있도록 링크를 달아주었다.

 

App.js

import "./styles.css";
import { Route, Routes } from "react-router-dom";
import Home from "./pages/Home";
import Product from "./pages/Product";

export default function App() {
  return (
    <div className="App">
      <Routes>
        <Route path="" element={<Home />} />
        <Route path="/product" element={<Product />} />
      </Routes>
    </div>
  );
}

Routes안에 Route들을 넣어주면 안에서 Path조건에 맞는 한 개의 Route만 렌더링 된다.

 

그리고 꼭 까먹지 말고 상위컴포넌트를 BrowserRouter로 감싸줘야 한다.

index.js

import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { BrowserRouter } from "react-router-dom";

import App from "./App";

const rootElement = document.getElementById("root");
const root = createRoot(rootElement);

root.render(
  <StrictMode>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </StrictMode>
);

URL 파라미터와 쿼리 스트링 (주소창에 데이터 전송)

페이지 주소를 정의할 때 가끔은 변하는 유동적인 값을 사용해야 할 때도 있다.
1 ) URL 파라미터 예시
Link에서 value를 전달

<Link to='/product/item1'> //


Route에서 키를 전달

<Route path='/product/:productname' element={<Product></Product>}/>


useParams( ); --> 객체를 리턴 // 해당주소가 들어가는 컴포넌트에서 값을 받음 아래의 객체를 리턴함

{
   productname:item1
}

Product.js

import React from 'react';
import { Link, useParams } from 'react-router-dom';
const data= {
    item1:{
        title:"아이폰",
        price: "150만원",
        desc:"비싸요 예뻐요"
    },
    item2:{
        title:"갤럭시",
        price:"30만원",
        desc:"싸고 예뻐요"
    }
}

const Product = () => {
    const {productname} = useParams(); //객체를 리턴 {productname:'item1'}
    const product = data[productname]
    return (
        <div>
            <h2>제품페이지</h2>
            <p>제품페이지 입니다.</p>
            {product ? <div>
                <h3>{product.title}</h3>
                <p>{product.price}</p>
                <p>{product.desc}</p>
            </div>:<p>존재하지 않는 페이지입니다.</p>}
            
        </div>
    );
};

export default Product;

Product에 data객체를 하나 만들어주고 useParams( )로 받아온 값을 data객체의 key값으로 넣어서

필요한 값을 받아왔다.

 

두 개의 값 중에 선택해서 받을 수 있도록 링크를 하나 더 만들어주자.

링크하나는 product/item1로 이동하고

두 번째는 product/item2로 이동하게 만들어준다.

 

2) 쿼리스트링 예시

<Link to='/about?name=green&age=30'>About</Link>

 

useLocation(  ) => 객체 리턴 location객체랑 똑같이 나옴

. search로 접근 ?name=green&age=30이렇게 나옴

useSearchParams( ) 배열을 리턴해줌--> [searchParams, setSearchParams]
searchParams.get("받아온 키값") //name, age

 

About.js

import React from "react";
import { useLocation, useSearchParams } from "react-router-dom";

const About = () => {
  const location = useLocation();
  const [searchParams, setParams] = useSearchParams();
  const name = searchParams.get("name");
  const age = searchParams.get("age");
  console.log(location);
  return (
    <div>
      <h2>소개페이지</h2>
      <p>소개페이지 입니다.</p>
      <p>{location.search}</p>
      <p>name값은{name}</p>
      <p>age값은{age}</p>
    </div>
  );
};

export default About;

쿼리스트링을 받을 페이지로 About컴포넌트를 만들어줬다. 쿼리스트링값을 두 가지 방법으로 받는데 

useLocation

useSearchParams로 받았다.

useLocation  은 location 객체를 받아주고  

useSearchParams는 location에서  search를 따로따로 떨어트려서 반환해 준다 반환해 준 값은. get(키값)

 


중첩된 루트 <outlet/>

app --> subpage --> subpage1
                                 subpage2
                                 subpage3

subpages 안에 subpage를 넣어주고  subpage컴포넌트 리턴 부분에 outlet을 넣어줌

<Route path='/subpages' element={<Subpages/>}>
      <Route path='/subpages/:id' element={<Subpage/>}/>
</Route>
return (
        <div>
            <li><NavLink to='/subpages/1'
            style={({isActive})=> isActive? activeStyle:undefined}
            >서브페이지1</NavLink></li>
            <li><NavLink to='/subpages/2'
            style={({isActive})=> isActive? activeStyle:undefined}
            >서브페이지2</NavLink></li>
            <li><NavLink to='/subpages/3'
            style={({isActive})=> isActive? activeStyle:undefined}
            >서브페이지3</NavLink></li>
            <Outlet/>
        </div>
    );


예제) 

우선은 링크가 많아지니 링크를 모아서 header컴포넌트에 넣어주도록 하겠다

Header.js

import React from "react";
import { Link } from "react-router-dom";

const Header = ({ sitename }) => {
  return (
    <div>
      <h1>{sitename}</h1>
      <ul>
        <li>
          <Link to="/">home</Link>
        </li>
        <li>
          <Link to="/about?name=green&age=30">About</Link>
        </li>
        <li>
          <Link to="/product/item1">iphone</Link>
        </li>
        <li>
          <Link to="/product/item2">galaxy</Link>
        </li>
        <li>
          <Link to="/subpages">서브페이지</Link>
        </li>
      </ul>
    </div>
  );
};

export default Header;

각 페이지로 이동하는 링크들을 모두 헤더에 넣어주고 h1태그에는 Props로 이름을 받아와서 넣어준다.

 

Subpages.js

import React from "react";
import { Link, Outlet } from "react-router-dom";

const Subpages = () => {
  return (
    <div>
      <li>
        <Link to="/subpages/1">서브페이지1</Link>
      </li>
      <li>
        <Link to="/subpages/2">서브페이지2</Link>
      </li>
      <li>
        <Link to="/subpages/3">서브페이지3</Link>
      </li>
      <Outlet />
    </div>
  );
};

export default Subpages;

 

subpages에서 각 서브페이지로 이동할 수 있는 링크를 만들고 서브페이지가 렌더링 되면 subpages내부에 렌더링 되기 때문에 <Outlet/>을 써서 보여준다.

Subpage.js

import React from "react";
import { useParams } from "react-router-dom";

const Subpage = () => {
  const { id } = useParams();
  return (
    <div>
      <h2>서브페이지{id}</h2>
    </div>
  );
};

export default Subpage;

보내주는 url값을 useParams로 받아서 id에 할당해 주고 h2태그에 넣어준다.

 

App.js

import "./styles.css";
import { Route, Routes } from "react-router-dom";
import Home from "./pages/Home";
import Product from "./pages/Product";
import About from "./pages/About";
import Header from "./components/Header";
import Subpage from "./pages/Subpage";
import Subpages from "./pages/Subpages";

export default function App() {
  return (
    <div className="App">
      <Header sitename="green" />
      <Routes>
        <Route path="" element={<Home />} />
        <Route path="/product/:productname" element={<Product />} />
        <Route path="/about" element={<About />} />
        <Route path="/subpages" element={<Subpages />}>
          <Route path="/subpages/:id" element={<Subpage />} />
        </Route>
      </Routes>
    </div>
  );
}

Route subpages 태그 안에 Route  Subpage를 넣어주었다. 이렇게 해주면

Route subpages가 렌더링 될 때 subpages도 조건이 일치하면 같이 렌더링 될 수 있다. (Outlet 써줘야 함)

 

useNavigate( )

Link컴포넌트를 사용하지 않고 다른 페이지로 이동을 해야 할 때 사용하는 Hook

const navigate = useNavigate();
navigate(-1)      //이전페이지로 이동
navigate(1)        //다음페이지로 이동
navigate('/product') 경로로 이동

 

Header.js

import React from "react";
import { Link, useNavigate } from "react-router-dom";

const Header = ({ sitename }) => {
  const navigate = useNavigate();
  const goback = () => {
    //이전페이지 이동
    navigate(-1);
  };
  const goSubpage = () => {
    //서브페이지 이동
    navigate("/subpages");
  };
  return (
    <div>
      <h1>{sitename}</h1>
      <ul>
        <li>
          <Link to="/">home</Link>
        </li>
        <li>
          <Link to="/about?name=green&age=30">About</Link>
        </li>
        <li>
          <Link to="/product/item1">iphone</Link>
        </li>
        <li>
          <Link to="/product/item2">galaxy</Link>
        </li>
        <li>
          <Link to="/subpages">서브페이지</Link>
        </li>
      </ul>
      <div>
        <button onClick={goback}>뒤로가기</button>
        <button onClick={goSubpage}>subpage</button>
      </div>
    </div>
  );
};

export default Header;

useNavigatenavigate변수에 할당해 주고 이전페이지로 이동하는 함수와 서브페이지로 이동하는 함수를 만들어서 버튼에 클릭이벤트로 넣어주었다.

<NavLink> 컴포넌트

링크에서 사용하는 경로가 현재 라우트의 경로와 일치하는 경우 특정 스타일 또는
css클래스를 적용하는 컴포넌트
<NavLink> 컴포넌트를 사용할 때에는 style 또는 className을 설정할 때

 {isActive:boolen}을 파라미터로 전달받는 함수 타입의 값을 전달함.

ex>

const activeStyle={
	backgroundColor:'pink',
	fontSize: 24
}

<NavLink style = {({isActive})=> isActive? activeStyle : undefined }/>
<NavLink className = {({isActive})=> isActive? "active" : undefined }/>

Subpages.js

import React from "react";
import { NavLink, Outlet } from "react-router-dom";

const Subpages = () => {
  const activeStyle = {
    backgroundColor: "pink",
    fontSize: 24
  };
  return (
    <div>
      <li>
        <NavLink
          to="/subpages/1"
          style={({ isActive }) => (isActive ? activeStyle : undefined)}
        >
          서브페이지1
        </NavLink>
      </li>
      <li>
        <NavLink
          to="/subpages/2"
          style={({ isActive }) => (isActive ? activeStyle : undefined)}
        >
          서브페이지2
        </NavLink>
      </li>
      <li>
        <NavLink
          to="/subpages/3"
          style={({ isActive }) => (isActive ? activeStyle : undefined)}
        >
          서브페이지3
        </NavLink>
      </li>
      <Outlet />
    </div>
  );
};

export default Subpages;

 서브페이지를 링크를 클릭하면 클릭한 링크의  isActive가 true가 되면서 스타일 이 적용된다.

 

NotFound 페이지 만들기

미리 정의되지 않는 경로에 사용자가 진입했을 때. 

보이는 페이지 페이지를 찾을 수 없을 때 나타나는 페이지

 

NotFound.js

import React from 'react';

const NotFound = () => {
    return (
        <div>
            404<br/>
            페이지를 찾을 수 없습니다      
        </div>
    );
};

export default NotFound;
<Route path="*" element={<Notfound/>}/>

 

 

예제)

 

 

리액트라우터 라이브러리는 페이지를 이동해줘야 하는 웹의 특성상 필수로 알아둬야 하고 또 잘 쓸 수 있어야 할 것 같다. 확실히 링크를 타고 다른 페이지로 이동되는 웹사이트보다 같은 페이지에서 계속 렌더링 시켜주는 방식이 화면전환이 더 깔끔하고 부드러워 보인다. 

반응형

+ Recent posts