🍎

nextjsで絞り込み検索の体験向上

に公開

はじめに

nextjsのチュートリアルを進めていて参考になる章があったのでまとめてみました。

こちらの3点を要件とします。

  • 検索ボックスに入力したらボタンをクリックまたはEnterキーを押さなくても自動で反映してほしい。
  • 反映する前は一時的にローディングuiを表示したい。
  • ページネーションを実装したい

今回開発する画面はこちらになります。

検索部分

  1. 検索文字が入力された時の関数
  const handleSearch = useDebouncedCallback((term) => {
    const params = new URLSearchParams(searchParams);
    params.set("page", "1");

    if (term) {
      params.set("query", term);
    } else {
      params.delete("query");
    }
    replace(`${pathname}?${params.toString()}`);
  }, 300);

term: 入力された文字
params.set(“query”, term)で入力内容をセットし、
replace(${pathname}?${params.toString()});でページ遷移しています。

useDebouncedCallbackは呼び出しから一定時間経たないと処理を実行しないreactのカスタムフックです。例えば「ABC」と入力した時にこのような違いがあります。

  • デバウンスなし
     入力内容が「A」→処理実行→「AB」→処理実行→「ABC」→処理実行
  • デバウンスあり
     入力内容が「A」→「AB」→「ABC」→0.3秒待機→処理実行
    これを入れることでサーバーの負担も少なくなり、ユーザー目線も画面がチラつくことがなくなります。
  1. 一時的なuiを表示する部分
  <Suspense key={query} fallback={<InvoicesTableSkeleton />}>
        <Table query={query} currentPage={currentPage} />
  </Suspense>

ここはreact標準のSuspenseコンポーネントを使用。
<Suspence>は子コンポーネントが読み込み中の間にローディングコンポーネントなどの一時的なuiを表示します。
今回はqueryが変化するごとに<InvoicesTableSkelton>を一時的に表示しました。
そしてこのような画面になります。(gif)

ページネーション部分

  const query = searchParams?.query || "";
  const currentPage = Number(searchParams?.page) || 1;
  const totalPages = await fetchInvoicesPages(query);

queryが変更されると合計のページ数をフェッチ

  const allPages = generatePagination(currentPage, totalPages);
  const createPageURL = (pageNumber: number | string) => {
    const params = new URLSearchParams(searchParams);
    params.set("page", pageNumber.toString());
    return `${pathname}?${params.toString()}`;
  };
  return (
    <>
      <div className="inline-flex">
        <PaginationArrow
          direction="left"
          href={createPageURL(currentPage - 1)}
          isDisabled={currentPage <= 1}
        />
     {allPages.map((page, index) => {
            return (
              <PaginationNumber
                key={`${page}-${index}`}
                href={createPageURL(page)}
                page={page}
              />
            );
          })}

ページネーションの矢印など数字のボタン部分のリンクをcreatePageURLで作成

ページネーションが実装されました(gif)

nextjsのチュートリアル

nextjsの勉強をするならチュートリアルがおすすめです。
https://nextjs.org/learn

NCDCエンジニアブログ

Discussion