Nextjsで検索機能の仕組みを理解
公開: 2025年12月14日
検索機能実装に関する仕組みを理解したくてまとめました。
茜先生に聞いたらNextjsもRailsも同じ仕組みだそう。
なので、まずはNextjsで理解。
備忘記録&アウトプットします。
補足等あれば教えてください<m(__)m>
※ここではフロントエンド側の検索状態管理にフォーカスするため、バックエンド(API / DB)の実装は割愛。
①ユーザーが検索ワードを入力
↓
②フロントが検索条件(keyword / page / sortなど)をAPIに送る
↓
③ APIが検索条件をもとにDBに問い合わせ
↓
④DBが条件に合うデータに絞り込み、一部(1ページ分など)を返す
↓
⑤フロントが結果を画面に表示
①URLから検索条件を読み取る(useSearchParams)
↓
②URLの値を初期値として useState にセット
↓
③ユーザーの入力で state が変わる
↓
④state の変更を検知して useEffect で URL を組み直し
↓
⑤ URLが変わることで、再び useSearchParams が最新の値を読み取り、検索状態がブラウザに反映される
これ、私ははじめ意味不明でした。
前提として、初期表示(検索前)のURLは以下。
https://shiftb.dev/blog
“検索”をキーワードに検索した時のURLって以下のようなURLになるんです。
(URLエンコードされる場合はある)
https://shiftb.dev/blog/?keyword=検索URLの ? より後ろ「?keyword=検索」が検索したいもの。
?keyword=検索
└──┬──┘ └─┬─┘
ラベル 値じゃあこれをコード上のもってくるコンポーネントがuseSearchParams()。
useSearchParamsは、今のURLについてる search params を読むための道具。
公式▼
https://nextjs.org/docs/app/api-reference/functions/use-search-params
フロント
'use client'
import { useSearchParams } from 'next/navigation'
export const SearchBar = () => {
const searchParams = useSearchParams()
const keyword = searchParams.get('keyword')
// URL -> `/blog ? keyword=検索`
// `keyword` -> '検索'
・・・
}・get()で、keywordというURL上のラベルに入っている値”検索”を取得。
※useSearchParams は、URL のクエリ文字列を読み取ることができるクライアント コンポーネントフックのため、数値(page など)を扱う場合、URLから取得した値はparseInt()などで数値に変換する必要あり。(上記コードはキーワード(文字列)のみの例)
フロント
const [searchKeyword, setSearchKeyword] = useState(keyword);・ useSearchParams は URL を「変更する」ことはできず、「読む専用」なので、stateで管理。
検索項目に別のキーワードが入る
フロント
useEffect(() => {
// 現在のURLのクエリパラメータを取得
const params = new URLSearchParams(window.location.search);
// stateの値をURLのkeywordに反映
params.set("keyword", searchKeyword);
// 新しいURLを生成。URL に使えるのは「文字列」だけなので文字列化忘れずに
const newUrl = `${window.location.pathname}?${params.toString()}`;
// ページ遷移せずにURL欄を更新
window.history.replaceState({}, "", newUrl);
}, [searchKeyword]);
・replaceState を使うことで、検索入力のたびに履歴が増えるのを防ぐ
検索状態を URL と state の両方で管理することで、操作性と再現性(リロード・共有)を両立した検索機能を実装できる。
実際の実務ではページネーションを使ったり複合検索&ソートしたりと、複雑になることが多いが、まずは基本から。。。
今日は茜さんのコードを見まくってます。ありがとうございます!
これを、Railsではバックエンド含めてどうするか、次学ぶ🔥
