💎 React

동적 라우팅 - Path Parameter 와 useParams

ji-hyun 2021. 12. 19. 18:16

Parameter

Parameter 는 매개변수라는 뜻

즉, url 경로에 매개변수를 도입할 수 있다!!

 

 

 

 

< 학습목표!! >

1. Path Parameter 와 Query Parameter 의 차이점에 대해서 설명할 수 있다.

2. useNavigate, useLocation, useParams 훅의 용도가 무엇인지 설명할 수 있다.

3. URL 에서 동적인 부분을 변수로 처리할 수 있고, 이를 통해 동적 라우팅 기능을 구현할 수 있다.

4. offset 과 limit 개념을 사용하여 페이지네이션 기능을 구현할 수 있다.

 

 

 

 

 

라우팅의 정의를 다시 살펴보면.... (다른 경로에 따라 다른 화면을 보여주는 것) 이다.

라우팅을 사용하는 이유는 -> 리액트는 SPA 이기 때문이다.

 

 

 

 

 

 

 

 

< 우리가 배운 기존의 라우팅 >

 

// Router.js
const Router = () => {
  return (
    <BrowserRouter>
	<Nav />
      <Routes>
        <Route path="/" element={<App />} />
        <Route path="/users" element={<Users />} />
        <Route path="/products" element={<Products />} />
        <Route path="*" element={<NotFound />} />
      </Routes>
	<Footer />
    </BrowserRouter>
  );
};

 

  • index.html : public/index.html에 위치하며 React 페이지 로드 시 가장 먼저 호출되는 영역
  • index.js : React 앱을 렌더하고 index.html의 div#root 이하에 끼워넣는 역할
  • Router.js : React 앱이 경로에 따라 어떤 컴포넌트를 보여줄지 결정하는 역할 (화면 바꿔 끼우기)

 

 

위와 같이 지금까지 해온 라우팅 방법은 정해진 경우(정해진 url)에서만 라우팅을 했다.

 

 

 

 

 

 

하지만 다른 사이트 보면 상세페이지 url 뒤에 id 값이 들어가는 경우가 있다. ( id=38585 이런 느낌쓰 )

이것은 우리가 일일히 작성해줄 순 없다.

 

 

Path Parameter

 

// Bad
"/users/1" => <Users id={1} />
"/users/2" => <Users id={2} />
"/users/3" => <Users id={3} />
"/users/4" => <Users id={4} />
"/users/5" => <Users id={5} />

 

// Good
"/users/:id" => <Users /> // useParams().id

 

이렇게 달라지는 부분을 매개변수로 처리하는 것이 좋다.

 

 

 

 

 

 

 

<BrowserRouter>
	<Routes>
		<Route path='/product/:id' element={<ProductDetail />} />
	</Routes>
</BrowserRouter>

 

① : 는 Path Parameter 가 올 것임을 의미

id 는 해당 Path Parameter 의 이름을 의미합니다. 변수 명을 짓듯이, 임의의 이름을 지정해줄 수 있습니다.

ex) :productId

 

 

 

 

 

 

 

갑자기 생각난 우리 팀에서 지적받은 예시....

 

// Bad

<Route
	path="/detail-blueEgg"
    element={<Detail ProductName="chicken" category="blueEgg" />}
/>
<Route
	path="/detail-yellowEgg"
    element={<Detail ProductName="chicken" category="yellowEgg" />}
/>

 

이렇게 상세페이지 라우팅을 정의해주었는데 지적 받았다.

 

 

 

 

 

 

 

Query Parameter

 

// Bad
"/search?keyword=위코드"    : <Search keyword="위코드" />
"/search?keyword=리액트"    : <Search keyword="리액트" />
"/search?keyword=라우팅"    : <Search keyword="라우팅" />
"/search?keyword=쿼리스트링" : <Search keyword="쿼리스트링" />
"/search?keyword=SPA"     : <Search keyword="SPA" />

 

// Good
"/search?keyword=something" : <Search /> // useLocation().search

 

 

Path Parameter 와 Query Parameter 랑 차이점이 뭘까?

1. 물음표

2. id는 하나의 정보만 있는데 쿼리 파라미터는 여러 정보 ㅇ

 

 

 

 

언제 사용하는게 좋을까?

1. Path Parameter(한가지 정보만) - 예를 들어 리스트에서 상세페이지 이동할때!!!!!!

2. Query Parameter(정보가 많을때) - 페이지네이션, 필터링!!!!!!!

 

 

 

페이지네이션은 콘텐츠를 여러 페이지로 나누고, 이전 혹은 다음 페이지로 넘어가거나 특정 페이지로 넘어갈 수 있는 일련의 링크를 페이지 상단이나 하단에 배치하는 방법입니다. 구글 검색 결과가 분명한 사례가 되겠지만, 페이지네이션은 블로그(이전/다음 포스트 링크)와 상당히 많은 이커머스 사이트에서도 발견할 수 있습니다. 

 

 

 

 

 

 

 

 

동적 라우팅 실습

상세페이지에서 정보만 달라지는데 (가격이라든가 상품이름) 이건 어떻게 하는지 몬스터 과제를 통해 알아보자!

 

 

 

다음은 url 이 바뀌는 모양이다. 이런 느낌으로 바꿔줄 것이다.

localhost:3000/monsters

localhost:3000/monsters/detail/3

 

 

 

 

 

 

 

메인페이지

 

// Monsters.js

import React, { useState, useEffect } from "react";
import SearchBox from "./Components/SearchBox/SearchBox";
import CardList from "./Components/CardList/CardList";
import "./Monsters.scss";

export default function Monsters(){
	const [monsters, setMonsters] = useState([]);
    
    useEffect(() => {
    fecth("")
    	.then((res) => res.json())
        .then((res) => setMonsters(res));
    }, []);
    
    return (
    	<div className="monsters">
        <h1>Project - Monsters</h1>
            <SearchBox />
            <CardList monsters={monsters} />
        </div>
    );
}




// Router.js
<Route path="/monsters" element={<UrlParameters />} />
<Route path="/monsters/detail/" element={<MonsterDetail />} />

 

카드에서 클릭할 때 이동한다.

따라서 카드리스트(CardList)에 이벤트 리스너가 붙어야 한다.

이때 CardList 에 monsters 변수를 넘겨준다.

 

 

 

메인페이지

 

 

 

 

 

CardList.js (리스트 페이지)

 

import React from "react";
import Card from "../Cart/Cart";
import "./CartList.scss";


export default function CardList({ monsters }){
	return (
    	<div className="cardList">
         {monsters.map((monstser) => {
          	return (
            	<Card
                	key={monster.id}
                    id={monster.id}
                    name={monster.name}
                    email={monster.email}
                />
             );
          })}
          </div>
     );
}

 

monsters 를 인자로 받는다.

각 카드에 monster 단수들을 보내준다.

카드 컴포넌트들을 만들어준다.

 

 

 

 

 

 

 

각 카드 컴포넌트는

 

// Card.js

import React from "React";
import {useNavigate} from "react-router-dom";
import "./Card/scss";

function Card(props){

	const navigate = useNavigate();   // 함수 반환됨
	const goToMonsterDetail = () => {
    	navigate(`/monsters/detail/${props.id}`);  //     상세페이지 / id값
    }



	return (
    	<div className="cardContainer" onClick={goToMonsterDetail}>
        	<img
            	src={`https://rovofsdfs.org/${props.id}?set=set2&size=180*180`}
                alt=""
            />
            <h2>{Props.name}</h2>
            <p>{Props.email}</p>
        </div>
    );
 }
 
 export default Card;

 

 

그런데 화면이 안나온다.

왜일까?

url 에 해당 페이지가 없어서..이다.

 

다시 말해서 이 url 에 해당하는 컴포넌트가 없어서이다. 그래서 아무 화면 안뜬다.

 

 

 

 

따라서 Router.js 파일에

 

// Router.js

<Route path="/monsters/detail/:monsterId" element={<MonsterDetail />} />

 

이렇게 뒤에 : 작성해야 함!

 

 

 

 

이제 상세페이지에서 아이템에 따른 정보를 가져와야 한다.

 

 

 

 

 

 

 

 

MonsterDetail 컴포넌트를 보자

 

import React, {useState} from "react";
import Card from "./Components/Card/Card";
import "./MonsterDetetail.scss";

function MonsterDetail(){
	const [monster, setMonster] = useState({});
    
    return (
    	<div className="urlParameters">
        	<div className"btnWrapper">
            	<button>Back to Monsters List</button>
            </div>
            <Card />
            <div className="btnWrapper">
            	<button>Previous</button>
                <button>Next</button>
            </div>
          </div>
       );
}

export default MonsterDetail;

 

 

상세페이지는 이러한 형태이다.

 

 

 

 

데이터를 받아오는 get 요청은 어디에서 해야할까?

-> useEffect

 

import React, {useState, useEffect } from "react";
import {useParams } from "react-router-dom";
// url 에 path parameter 정보를 내려 받아오고 싶을때
// useParams 훅을 이용한다.
// 어떤 객체가 반환된다.
import Card from "./Components/Card/Card";
import "./MonsterDetetail.scss";

function MonsterDetail(){
	const [monster, setMonster] = useState({});
    
    const params = useParams();
    
    console.log(params);   // 결괏값을 확인해보자 
   
    
    
    useEffect(()=> {
    fetch(`/users/:${params.monterId}`')
    	.then((res) => res.json())
        .then((res) => console.log(''));  
    }, []);
    
    
    return (
    	<div className="urlParameters">
        	<div className"btnWrapper">
            	<button>Back to Monsters List</button>
            </div>
            <Card />
            <div className="btnWrapper">
            	<button>Previous</button>
                <button>Next</button>
            </div>
          </div>
       );
}

export default MonsterDetail;

 

 

 

콘솔로그 결과이다.

params 는 객체이고, 

monstserId 라는 프로퍼티가 나오는데 이 프로퍼티는 아무데서나 나오는 것이 아니라

 

Router.js 파일에서

<Route path="/monstsers/detail/:monsterId" element={<MonsterDetail />} />

 

여기서 온 것이다.

 

 

 

 

import React, {useState, useEffect } from "react";
import {useParams } from "react-router-dom";
// url 에 path parameter 정보를 내려 받아오고 싶을때
// useParams 훅을 이용한다.
// 어떤 객체가 반환된다.
import Card from "./Components/Card/Card";
import "./MonsterDetetail.scss";

function MonsterDetail(){
	const [monster, setMonster] = useState({});
    
    const params = useParams();
   
    
    
    useEffect(()=> {
    fetch(`/users/:${params.monterId}`')
    	.then((res) => res.json())
        .then((res) => setMonster(res));   // 이렇게 받아온 정보를 setMonstser 에 넣어주자
    }, []);
    
    
    return (
    	<div className="urlParameters">
        	<div className"btnWrapper">
            	<button>Back to Monsters List</button>
            </div>
            <Card id={monster.id} name={monstesr.name} email={monster.email} />
            <div className="btnWrapper">
            	<button>Previous</button>
                <button>Next</button>
            </div>
          </div>
       );
}

export default MonsterDetail;

 

이렇게 카드 컴포넌트에 잘 전달해주면 된다.

 

 

 

 

 

 

< useNavigate, useLocation, useParams 훅의 용도 >

useNavigate // url을 변경하는 함수

useLocation // 현재 페이지의 경로 정보를 담고 있는 객체를 반환

useLocation

여기서 search 프로퍼티는 Query Parameter 에 대한 정보를 담고 있다. 이는 필터링에 이용할 수 있다. 다음에 알아볼 것!!

 

Query Parameter 예시)

?offset=10&amp;limit=123

 

 

 

 

 

useParams // 현재 페이지의 path parameter 의 정보를 담고 있는 객체를 반환

 

 

 

 

 

 

 

 

 

 

 

 

 

'💎 React' 카테고리의 다른 글

React + Node Express 필터링  (0) 2022.03.01
리액트 페이지네이션 - Query Parameter  (0) 2021.12.26
styled-components  (0) 2021.12.13
리액트 토큰 유무에 따른 UI 변경  (0) 2021.12.09
리액트 204 에러  (0) 2021.12.08