Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Next.jsでクエリパラメータを楽に扱おう nuqsを紹介!

imaimai17468
September 06, 2024
700

Next.jsでクエリパラメータを楽に扱おう nuqsを紹介!

imaimai17468

September 06, 2024
Tweet

Transcript

  1. Next.jsでのクリパラメータでの扱い router.queryを使う const router = useRouter(); // ... router.push({pathname: "hoge",

    query: {id: router.query.id}}); useSearchParamsを使う const searchParams = useSearchParams(); // ... <Link href={{pathname: "hoge", query: {id: searchParams.get("id")}}}> Link </Link> 4
  2. 豊富なparserの種類 string number (integer, float, hex) boolean literal (string, numeral)

    enum date & timestamp array json (with zod scheme) なんなら自分で作れる (createParser) 8
  3. 複数のqueryを定義したい場合 それぞれのqueryを非同期に更新できる const [isCheck, setIsCheck] = useQueryState('count', parseAsBoolean.withDefault(false)) const [name,

    setName] = useQueryState('name', parseAsString) // ... return ( <div> <input value={isCheck} onChange={e => setName(e.target.value)} /> <input value={name || ''} onChange={e => setName(e.target.value)} /> </div> ) 9
  4. Option パーサーに複数のオプションを渡すことができる parseAsString.withOptions({ history: 'push' }) history // 履歴が置き換えられる useQueryState('foo',

    { history: 'replace' }) // 新しく履歴が追加される useQueryState('foo', { history: 'push' }) historyのhackはbad UXにつながる可能性があるので注意 10
  5. shallow クエリパラメータの更新によるルーティング範囲の切り替え useQueryState('foo', { shallow: true }) true クライアントで完結 false

    サーバーまで通知されて、場合によっては再レンダリングされる queryによって即座にfetchさせたい場合など ハードナビゲーション 11
  6. Serialize nuqsで定義したqueryを型安全にurl文字列で出力できる const searchParams = { search: parseAsString, limit: parseAsInteger,

    sortBy: parseAsStringLiteral(['asc', 'desc'] as const) } const serialize = createSerializer(searchParams) serialize("/hoge", { search: 'foo bar', limit: 10, sortBy: 'asc' }) // -> /hoge/?search=foo+bar&limit=10&sortBy=asc 検索フォームなどは の関数をLinkコンポーネントで渡すだけでよくなる 12
  7. Server Componentsでの利用 1. queryの定義・cacheとserializeの定義をする const searchParams = { q: parseAsString.withDefault(''),

    maxResults: parseAsInteger.withDefault(10) } export const searchParamsCache = createSearchParamsCache(searchParams) export const serialize = createSerializer(searchParams); 13
  8. 2. ページロード時のsearchParamsと同期をとる clientでのuseQueryStateのsetを初期で行うイメージ export default function Page({ searchParams }: {

    searchParams: Record<string, string | string[] | undefined> }) { const searchParamsCache.parse(searchParams) // ... } 14
  9. 3. cacheは .all または .get で取得可能 ナビゲーションによってクエリのcacheが更新される const { q,

    maxResults } = searchParamsCache.all(); const setQuery = (query: string) => { return serialize("/", { q: query, maxResults }); }; return ( <Link href={setQuery("test-query")}}>Link</Link> ) stateとのリアルタイムな同期は流石にClient Componentが必要 ただしsearchParamsCacheとuseQueryStateとの連携は可能 15
  10. 蛇足 Next.jsがソフトナビゲーションにqueryの更新ができる <Form /> コンポーネントを作 っているらしい import Form from 'next/form'

    export default function Page() { return ( <Form action="/search"> <input name="query" /> <button type="submit">Submit</button> </Form> ) } Components: <Form> | Next.js 16