[React] Advanced Router

jini.choi·2023년 7월 9일
0

westudy

목록 보기
7/7

🚀 학습 목표

  • 동적 라우팅(Dynamic Routing)의 개념에 대해서 설명할 수 있다.
  • 컴포넌트에서 Path Parameter를 가져와 활용할 수 있다.
  • 쿼리 스트링(Query String)의 개념과 형태에 대해서 설명할 수 있다.
  • 컴포넌트 내에서 URL의 쿼리 스트링을 가져와 활용할 수 있다.

동적 라우팅(Dynamic Routing)의 개념에 대해서 설명할 수 있다.

  • 동적 라우팅은 Route를 설정할 때 URL의 전체 형태를 미리 정의하는 것이 아닌, 특정 규칙을 정의한 후 규칙에 부합하는 URL의 경우에는 해당 element를 보여주게 설정하는 방식

-/post/1, /post/2처럼 1, 2와 같은 숫자까지 포함해서 URL의 전체 형태를 미리 정의하는 것이 아닌,/post/로 시작하는 모든 URL은 상세페이지로 연결되게 설정

react-router-dom을 이용한 동적 라우팅의 구현

  • react-router-dom에서 동적 라우팅을 구현하는 방법은 Route 컴포넌트의 path prop에 : 기호를 활용
  • 경로/:문자열형태로 path를 설정하면 URL에서 경로/ 뒤에 무슨 글자가 오든 이 Route로 연결
  • : 기호 뒤에 붙는 id 와 같은 문자열이 path parameter
import React from 'react';
import { BrowserRouter, Route, Routes } from 'react-router-dom';

export default function Router() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<ListComponent />} />
        <Route path="/post/:id" element={<DetailPageComponent />} />
      </Routes>
    </BrowserRouter>
  );
}

path parameter

  • path parameter는 URL에 있는 값을 마치 매개변수(parameter)처럼 사용

  • 똑같은 함수에 다른 매개변수를 통해서 다양한 결과를 낼 수 있는 것처럼 path parameter를 통해서 큰 틀은 동일하되 다른 UI를 보여주도록 처리할 수 있다.

  • Route의 path prop에 경로/:문자열을 넣어줘야 한다고 했다. 이때 문자열 자리에 작성되는 것이 바로 path parameter의 이름


컴포넌트에서 Path Parameter를 가져와 활용할 수 있다.

useParams hook

  • react-router-dom에서는 useParams hook을 제공

  • useParams hook은 path parameter의 값을 편하게 가져올 수 있게 해주며, state처럼 path parameter의 값이 바뀌면 컴포넌트를 리렌더링 해주는 기능 제공

  • useParams hook을 호출하면 path params의 값을 객체 형태로 반환.
    이때 객체의 프로퍼티의 key는 Route에서 설정한 path parameter의 이름이며 value는 path parameter에 실제로 전달된 값.
    즉 블로그 애플리케이션에서는 path parameter의 이름을 id로 지정을 했기 때문에 post/1로 접속했다면 useParams hook의 return 값은 {id: 1}이 되는 것

mport { useParams } from 'react-router-dom';

const params = useParams();

쿼리 스트링(Query String)의 개념과 형태에 대해서 설명할 수 있다.

  • /list페이지로 유저가 접속했을 때 상품이 1억개하면 1억개의 상품 동류를 모두 보여주는 것은 비효율 적

  • 1억개의 상품 정보를 모두 가져와야하기 때문에 오래걸리고, 실제 유저는 판매량순으로 10개, 최신순으로 10개, 리뷰평점순으로 10개처럼 더 정렬되고 특정된 형태의 정보를 보고싶어하기 때문

  • 우리는 단순히 "상품리스트를 보여줘"가 아닌 "상품 리스트를 최신순으로 상위 10개만 보여줘"처럼 구체적으로 요청할수 있어야 하고 이때 활용하는 것이 쿼리스트링이다.

쿼리 스트링의 형태

(출처: https://www.semrush.com/)

  • 이름 그대로 문자열 형태, key=value로 표현됨

  • 페어갯수 제한 없음

  • https://www.example.com/products?sort=popular 이 예시에서 정렬 기준을 나타내는 sort 외에 데이터를 오름차순 또는 내림차순으로 표시할지에 대한 정보인 정렬 방향에 대한 정보를 추가로 포함한다면
    https://www.example.com/products?sort=popular&direction=desc 와 같이 표현해서 여러 개의 key=value 페어가 포함된 형태로 쿼리스트링을 만들 수 있다.

react-router-dom에서 쿼리 스트링의 사용

  • Router 컴포넌트에서 별도의 Route를 만들거나 path prop의 값을 수정하거나 할 필요는 없음.
  • 마찬가지로 쿼리 스트링을 포함해서 Routing을 할 때도 특별히 다른 방법을 통해서 할 필요는 없다. <Link to="/list?sort=popular" />, navigate("/list?sort=popular")처럼 단순하게 Link 컴포넌트나 navigate 함수의 인자에 쿼리 스트링이 포함된 URL을 전달해주면 됨.

컴포넌트에서 쿼리 스트링 값 가져오기

  • useLocation, useSearchParams

  • react-router-dom에서는 쿼리 스트링의 값을 편하게 가져올 수 있는 hook 들을 제공. 이 hook 들을 이용하면 쿼리 스트링의 값을 편하게 가져올 수 있으며, state처럼 쿼리 스트링의 값이 바뀌면 컴포넌트를 리렌더링 해주는 기능을 제공


💻 useLocation hook

  • 현재 Location 객체를 리턴

  • Location 객체는 말 그대로 현재 위치(URL)에 포함된 여러 가지 정보를 가지고 있고 각각의 정보를 pathname, search, hash, state, key 등의 프로퍼티로 표현(Location 객체의 state 프로퍼티는 React의 state와는 다름)

  • 쿼리 스트링을 나타내는 프로퍼티는 search

  • Location 객체의 search 프로퍼티에는 URL 중 쿼리 스트링에 대한 정보가 문자열 형태로 저장되어 있다. 이를 활용해서 쿼리 스트링의 값을 획득하고 사용

// src/List.js

import React from 'react';
import { useLocation } from 'react-router-dom';

const List = () => {
  const location = useLocation();
  const queryString = location.search;

  return (
    <section>
      <h1>This is List Page</h1>
      <p>
        쿼리 스트링: <b>{queryString}</b>
      </p>
    </section>
  );
};

export default List;

다만!
전체 쿼리 스트링을 하나의 문자열 형태(?sort=popular)로 표현해 주기에 이 중에서 원하는 값만 가져오려면 저 문자열을 자바스크립트를 통해서 Parsing 하는 과정을 거쳐야 한다. 예를 들어 위 쿼리 스트링에서 sort의 값을 얻어내고자 한다면 ?를 문자열에서 제거하고, sort 문자열을 찾아내고, = 뒤에 위치한 값을 최종적으로 꺼내오는 과정을 거쳐야지만 최종으로 원한 결과값인 popular를 획득할 수 있다.

지금은 쿼리 스트링에서 하나의 key=value 페어밖에 존재하고 있지 않지만, 만약 여러 개의 key=value 페어가 존재해서 & 가 추가된다면 이 과정은 더 복잡해질 것.
또한, 만약 하나의 key 값에 여러 value를 표현하고 있는 형태(?sort=popular&sort=latest)의 쿼리 스트링에서 배열의 형태로 sort=["popular", "latest"] 같이 값을 추출하고자 한다면 더더욱 복잡해질 것.

이러한 과정을 거치지않고 원하는 값만 얻을 수 있도록 다양한 메서드를 제공해주는 URLSearchParams라는 객체가 있고

react-router-dom에서는 쿼리 스트링의 값을 이용해서 URLSearchParams 객체를 리턴해주는 useSearchParams라는 hook을 제공


💻 useSearchParams hook

  • useSearchParams hook을 호출하면 useState와 비슷하게 배열의 형태로 searchParams와 setSearchParams 함수를 리턴

  • searchParams는 URLSearchParams 객체이며 URLSearchParams 객체는 쿼리 스트링을 다루기 위한 여러 편리한 메서드를 제공

  • setSearchParams는 함수를 호출하면서 인자로 객체 또는 문자열을 넣어주면 현재 URL의 쿼리 스트링을 변경하는 기능을 제공

const [searchParams, setSearchParams] = useSearchParams();
  • searchParams에 정의된 메서드를 호출해서 쿼리 스트링에서 원하는 값을 편리하게 가져올 수 있다. 자주 사용되는 메서드는 아래와 같다.

1. 값을 읽어오는 메서드

  • searchParams.get(key) : 특정한 key의 value를 가져오는 메서드.
    원하는 쿼리 스트링의 key를 인자로 넣어서 메서드를 호출하면 해당 key에 부합하는 value가 리턴.

  • searchParams.getAll(key) : 특정한 key에 부합하는 value가 두 개 이상일 경우 라면 get 메서드는 제일 먼저 나온 value만 리턴.
    만약 모든 value 값들을 얻고 싶다면 getAll 메서드를 이용. getAll 메서드는 해당 key에 해당하는 모든 value를 배열의 형태 리턴.

    ?sort=popular&sort=latest의 경우
    searchParams.get("sort")의 리턴값: "popular"
    searchParams.getAll("sort")의 리턴값: ["popular","latest"]

  • searchParams.toString() : 쿼리 스트링을 string 형태로 리턴.
    searchParams는 객체이기 때문에 여기서 가공되지 않은 쿼리 스트링의 값을 그대로 얻고 싶다면 toString 메서드 호출.

    ?sort=popular&sort=latest의 경우
    searchParams.toString()의 리턴값: "?sort=popular&sort=latest"

2. 값을 변경하는 메서드

  • searchParams.set(key, value) : 메서드를 호출하면서 인자로 전달한 key 값을 value로 설정하는 메서드. 만약 동일한 key에 여러 value가 이미 존재하고 있었다면, set 메서드를 호출하면서 설정한 값 외에는 삭제.

    ?sort=popular&sort=latest 의 경우
    searchParams.set("sort", "clear") 호출
    searchParams.toString()의 리턴값: "?sort=clear"

  • searchParams.append(key, value) : 메서드를 호출하면서 인자로 전달한 key 값을 value로 추가하는 메서드. set 메서드와는 다르게 기존의 값들을 변경하거나 삭제하지 않고 추가하는 방식으로 동작.

    ?sort=popular&sort=latest 의 경우
    searchParams.append("sort", "clear") 호출
    searchParams.toString()의 리턴 값: "?sort=popular&sort=latest&sort=clear"

  • searchParams를 변경하는 메서드를 이용해서 searchParams의 값을 변경하더라도 실제 URL의 쿼리 스트링은 변경되지 않음. 변경된 searchParams를 이용해서 실제 쿼리 스트링을 변경시키려면 setSearchParams 함수에 searchParams를 인자로 전달하면서 호출해야함.

// src/List.js
// URL: /list?sort=popular&sort=latest

import React from 'react';
import { useSearchParams } from 'react-router-dom';

const List = () => {
  const [searchParams, setSearchParams] = useSearchParams();

  const setSortParams = () => {
    searchParams.set('sort', 'clear');
    setSearchParams(searchParams);
  };

  const appendSortParams = () => {
    searchParams.append('sort', 'hello-world');
    setSearchParams(searchParams);
  };

  return (
    <section>
      <h1>This is List Page</h1>
      <p>
        toString: <b>{searchParams.toString()}</b>
      </p>
      <p>
        get("sort"): <b>{searchParams.get('sort')}</b>
      </p>
      <p>
        getAll("sort"):
        {searchParams.getAll('sort').map((value) => (
          <b key={value}>{value} </b>
        ))}
      </p>
      <button onClick={setSortParams}>setSortParams</button>
      <button onClick={appendSortParams}>appendSortParams</button>
    </section>
  );
};

export default List;
profile
개발짜🏃‍♀️

0개의 댓글