반응형
Dynamic Routing (동적 라우팅)
정적 Routing
- Routing을 설정하는 가장 기본적인 방식은 정적 Routing이다.
- 정적 라우팅은 Router 컴포넌트에서 미리 프로젝트에 사용할 경로들과 보여줄 컴포넌트들을 모두 정의해두는 방식이다.
import React from 'react';
import { BrowserRouter, Route, Routes } from 'react-router-dom';
const Router = () => {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Main />} />
<Route path="/post/1" element={<PageOne />} />
<Route path="/post/2" element={<PageTwo />} />
<Route path="/post/3" element={<PageThree />} />
</Routes>
</BrowsweRouter>
)
}
export default Router;
-
- 하지만 복잡하고 규모가 큰 애플리케이션에서는 경로를 미리 설정하는 Routing 방식만으론 처리하기 힘든 작업이 존재할 수 있다.
- (Route를 유연하게 정의할 수 없으므로)
동적 라우팅 (Dynamic Routing) 이란?
- 동적 Routing은 경로를 미리 정해두지 않고 동적으로 설정하는 방식이다.
- 동적 Routing은 기존 (정적 Routing) 방식처럼 Route 설정 시 URL 전체의 형태를 미리 정의하지 않는다.
- 대신 특정 규칙을 만들고, 그 규칙과 부합하는 URL이 있을 경우에만 해당 element를 화면에 보여주는 방식으로 정적 Routing의 문제를 해결한다.
- 특정 규칙의 예시 : /post/로 시작하는 모든 URL은 상세페이지로 연결된다.
- 동적 Routing을 사용하면 /post/1 ,/post/1000, /post/100000 등 규칙을 만족하는 모든 URL을 상세페이지로 연결시킬 수 있기 때문에 더 확장성 있는 애플리케이션을 개발할 수 있다.
- 따라서 포스트가 추가되거나 삭제되는 등 변동이 생긴다 하더라도 Router 컴포넌트를 직접 수정할 필요가 없다.
- react-router-dom에서 동적 라우팅을 구현하는 방법은 Route 컴포넌트의 path prop에 : 기호를 활용하는 것이다.
- 경로/:문자열형태로 path를 설정하면 URL에서 경로/ 뒤에 무슨 글자가 오든 이 Route로 연결된다.
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>
);
}
- 여기서 : 기호 뒤에 붙는 문자열(id)이 path parameter이다.
- path parameter는 URL에 있는 값을 마치 매개변수(parameter)처럼 사용하는 것이다.
- path parameter를 이용하면 사용자가 같은 페이지로 접속하더라도, 큰 틀은 동일하되 다른 UI를 보여주도록 처리할 수 있다.
Hook
useParamsuseParams는 react-router-dom에서 제공하는 React Hook으로, path params의 값을 객체 형태로 반환해준다.
- key : Route에서 설정한 path paramenter의 이름
- value : Route에서 설정한 path paramenter에 실제로 전달된 값
- /post/:id로 path를 설정했을 때, 유저가 /post/1로 접속할 경우 useParams가 반환하는 객체의 key는 id이고, value는 1이다.
// src/Router.js
import { BrowserRouter, Routes, Route } from "react-router-dom";
import List from "./pages/List";
import Detail from "./pages/Detail";
const App = () => {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<List />} />
<Route path="/detail/:id" element={<Detail />} />
</Routes>
</BrowserRouter>
);
};
export default App;
// src/Detail.js
import React, { useState, useEffect } from "react";
import { useParams } from "react-router-dom";
const Detail = () => {
const { id } = useParams();
const [user, setUser] = useState({});
useEffect(() => {
fetch(`https://reqres.in/api/users/${id}`)
.then((response) => response.json())
.then((result) => setUser(result.data));
}, [id]); // 4
const { first_name, email, avatar } = user;
return (
<section>
<article>
<p>
<strong>{first_name}</strong>
</p>
<p>{email}</p>
<img alt="avatar" src={avatar} />
</article>
</section>
);
};
export default Detail;
- createBrowserRouter를 사용하여 라우터를 구현했을 때의 Router.jsx 코드는 아래와 같다.
// src/Router.jsx
import { createBrowserRouter } from "react-router-dom";
import Home from "./screens/Home";
import About from "./screens/About";
import User from "./screens/users/User";
import Root from "./Root";
import NotFound from "./components/NotFound";
import ErrorComponent from "./components/ErrorComponent";
const router = createBrowserRouter([
{
path: "/",
element: <Root />,
children: [
{
path: "",
element: <Home />,
errorElement: <ErrorComponent />,
},
{
path: "about",
element: <About />,
},
{
path: "users",
element: <User />,
children: [
{
path: ":userId",
element: <User />,
},
],
},
],
errorElement: <NotFound />,
},
]);
export default router;
Query String (쿼리 스트링)
- 쿼리 스트링이란 URL의 한 부분으로서, URL에 '오름차순 정렬'과 같은 구체적인 정보를 포함하고자 할 때 사용한다.
- 규모가 크고 복잡한 애플리케이션에서 단순한 형태의 요청은 비효율을 발생할 수 있기 때문에 (예를 들어 모든 데이터를 매번 다 가져와야 하는 경우) 쿼리 스트링을 사용한다.
Query String의 형태
- 쿼리 스트링은 key=value 형태의 문자열로 표현한다.
- URL에서 쿼리 스트링의 시작점은 ? 문자를 통해 표시된다.
- 쿼리 스트링 내에서 각각의 key=value 페어를 구분할 때 & 문자를 사용한다.
react-router-dom에서 쿼리 스트링의 사용
- URL에 쿼리 스트링을 포함시켜주면 된다. 특별한 설정을 할 필요는 없다.
- Link 컴포넌트 예시 : <Link to="/list?sort=popular" />
- navigate 함수 예시 : navigate("/list?sort=popular")
컴포넌트에서 쿼리 스트링 값 가져오기
- 쿼리 스트링을 포함해서 Routing을 해줬다면 이제는 컴포넌트에서 쿼리 스트링의 값을 가져올 수 있어야 한다.
- react-router-dom에서는 쿼리 스트링의 값을 편하게 가져올 수 있는 hook들을 제공한다.
- 이 hook들을 이용하면 쿼리 스트링의 값을 편하게 가져올 수 있으며, state처럼 쿼리 스트링의 값이 바뀌면 컴포넌트를 리렌더링 해주는 기능을 제공한다.
- useLocation Hook, useSearchParams Hook
Hook
useLocation- useLocation Hook은 현재 Location 객체를 리턴한다.
- Location 객체는 현재 위치(URL)에 포함된 여러 가지 정보를 가지고 있다.
- 객체 프로퍼티 : pathname, search, hash, state, key
- 이 중 쿼리 스트링을 나타내는 프로퍼티는 search이다.
(문자열 형태로 제공된다. 예 : "?sort=popular&sort=latest")
// src/List.js
import React from "react";
import { useLocation } from "react-router-dom";
const List = () => {
const { pathname, search, hash, state, key } = useLocation();
return (
<section>
<h1>This is List Page</h1>
<p>
쿼리 스트링: <b>{search}</b>
</p>
</section>
);
};
export default List;
Hook
useSearchParams- useSearchParams Hook은 useLocation Hook을 통해 가져온 쿼리 스트링 (예 : ?sort=popular&sort=latest) 에서 원하는 값만 꺼내올 수 있도록 도와주는 도구이다.
- useSearchParams Hook은 URLSearchParams 객체를 반환한다. 이 객체는 쿼리 스트링을 다루기 위한 여러 편리한 메서드를 제공한다.
-
const [searchParams, setSearchParams] = useSearchParams();
값을 읽어오는 메소드
- searchParams.get(key) : 쿼리 스트링에서 특정 key의 value 값 반환 (하나만)
- searchParams.getAll(key) : 쿼리 스트링에서 특정 key의 모든 value 값을 배열로 반환
- searchParams.toString() : 객체 형태의 쿼리 스트링을 문자열 형태로 반환
값을 변경하는 메소드
- searchParams.set(key, value) : 인지로 전달한 key값을 인자로 전달한 value로 덮어씌우는 메소드
- "?sort=popular&sort=latest" 의 경우
searchParams.set("sort", "clear") 호출 시
searchParams.toString()의 리턴값 : "?sort=clear"
- "?sort=popular&sort=latest" 의 경우
- searchParams.append(key, value) : 인지로 전달한 key값을 인자로 전달한 value로 추가하는 매소드 (기존 값은 수정하지 않음)
- "?sort=popular&sort=latest" 의 경우
searchParams.set("sort", "clear") 호출 시
searchParams.toString()의 리턴값 : "?sort=clear"
- "?sort=popular&sort=latest" 의 경우
- 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;
반응형
'◼ FrontEnd > ReactJS' 카테고리의 다른 글
[React] 카카오맵 API를 통해 지도를 화면에 띄우기 (에러 해결법) (0) | 2023.08.12 |
---|---|
[ReactJS] 관심사의 분리와 Custom Hook (0) | 2023.02.21 |
[ReactJS] Component의 분리와 재사용 (관심사의 분리) (0) | 2023.01.24 |
[ReactJS] 상수 데이터 & Mock Data + fetch 매소드 (0) | 2023.01.24 |
[ReactJS] Side Effect와 useEffect (0) | 2023.01.24 |