03. URL Params, useSearchParams(), useNavigate(), useSearchParams()

유승욱·2024년 5월 10일
0

Spring&React Project

목록 보기
3/9

현재 하나의 라우팅 설정에 children 속성을 이용해서 중첩적인 라우팅 설정을 적용할 수 있지만 페이지가 많아지면 페이지가 너무 복잡해지는 단점이 있다. 그래서 별도의 파일을 만들어 관리하고자 한다.
todoRouter.js

import { Suspense, lazy } from "react";

const Loading = <div>Loading...</div>;
const TodoList = lazy(() => import("../pages/todo/ListPage"));

const todoRouter = () => {
  return [
    {
      path: "list",
      element: (
        <Suspense fallback={Loading}>
          <TodoList />
        </Suspense>
      ),
    },
  ];
};

export default todoRouter;

리다이렉션 처리

'/todo/' 경로로 이동할 경우 자동으로 '/todo/list'로 이동하게끔 바꿔주었다.

import { Suspense, lazy } from "react";
import { Navigate } from "react-router-dom";

const Loading = <div>Loading...</div>;
const TodoList = lazy(() => import("../pages/todo/ListPage"));

const todoRouter = () => {
  return [
    {
      path: "list",
      element: (
        <Suspense fallback={Loading}>
          <TodoList />
        </Suspense>
      ),
    },
    {
      path: "",
      element: <Navigate replace to="list" />,
    },
  ];
};

export default todoRouter;

URL Params 사용하기


ReadPage.js

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

const ReadPage = () => {
  const { tno } = useParams();
  return (
    <div className="text-3xl font-extrabold">
      Todo Read Page Component {tno}
    </div>
  );
};

export default ReadPage;

useSearchParams()

useParams()가 경로 자체의 값을 사용하는데 비해 '?' 이후에 나오는 쿼리스트링은 useSearchParams()를 이용할 수 있다. 예를 들어 목록 페이지에는 페이징/검색 기능으로 인해서 '/todo/list?page=3&size=20'과 유사한 형태의 경로와 쿼리스트링이 사용되는데 이 경우 useSearchParams()를 이용해서 원하는 쿼리스트링의 값을 추출할 수 있다.
ListPage.js

import { useSearchParams } from "react-router-dom";

const ListPage = () => {
  const [queryParams] = useSearchParams();

  const page = queryParams.get("page") ? parseInt(queryParams.get("page")) : 1;
  const size = queryParams.get("size") ? parseInt(queryParams.get("size")) : 10;
  return (
    <div className="p-4 w-full bg-white">
      <div className="text-3xl font-extrabold">
        Todo List Page Component {page} --- {size}
      </div>
    </div>
  );
};

export default ListPage;

useNavigate()

React-Router를 이용하면 고정된 링크로 이동할 때도 있지만, 대부분은 상황에 따라서 동적으로 데이터를 처리해서 이동하는 경우가 많다. 이럴 때는 Navigator나 Link 대신 useNavigate()를 이용한다.

import { useCallback } from "react";
import BasicLayout from "../../layouts/BasicLayout";
const { Outlet, useNavigate } = require("react-router-dom");

function IndexPage() {
  const navigate = useNavigate();

  const handleClickList = useCallback(() => {
    navigate({ pathname: "list" });
  });
  const handleClickAdd = useCallback(() => {
    navigate({ pathname: "add" });
  });
  return (
    <BasicLayout>
      <div className="w-full flex m-2 p-2">
        <div
          className="text-xl m-1 p-2 w-20 font-extrabold text-center underline"
          onClick={handleClickList}
        >
          LIST
        </div>
        <div
          className="text-xl m-1 p-2 w-20 font-extrabold text-center underline"
          onClick={handleClickAdd}
        >
          ADD
        </div>
      </div>
      <div className="flex flex-wrap w-full">
        <Outlet />
      </div>
    </BasicLayout>
  );
}

export default IndexPage;

useSearchParams()

조회 페이지는 다시 목록으로 이동할 수 있기 때문에 page와 size처럼 쿼리스트링으로 전달되는 데이터들을 유지하면서 이동해야 한다. useSearchParams()를 이용해서 쿼리스트링으로 전달된 데이터를 확인하고 createSearchParams()라는 함수를 이용해서 이동 시에 필요한 쿼리스트링을 만들어내서 navigate()를 이용한 이동 시에 활용한다.

import { useCallback } from "react";
import {
  createSearchParams,
  useNavigate,
  useParams,
  useSearchParams,
} from "react-router-dom";

const ReadPage = () => {
  const { tno } = useParams();
  const navigate = useNavigate();
  const [queryParams] = useSearchParams();
  const page = queryParams.get("page") ? parseInt(queryParams.get("page")) : 1;
  const size = queryParams.get("size") ? parseInt(queryParams.get("size")) : 10;
  const queryStr = createSearchParams({ page, size }).toString();
  const moveToModify = useCallback(
    (tno) => {
      navigate({ pathname: `/todo/modify/${tno}`, search: queryStr });
    },
    [tno, page, size]
  );
  return (
    <div className="text-3xl font-extrabold">
      Todo Read Page Component {tno}
      <div>
        <button onClick={() => moveToModify(tno)}>Test Modify</button>
      </div>
    </div>
  );
};

export default ReadPage;

업로드중..

0개의 댓글