Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Next.jsでクエリパラメータを楽に扱おう nuqsを紹介!
Search
imaimai17468
September 06, 2024
2.2k
3
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Next.jsでクエリパラメータを楽に扱おう nuqsを紹介!
imaimai17468
September 06, 2024
More Decks by imaimai17468
See All by imaimai17468
オートメーション・バカにならないために
imaimai17468
1
290
MVP先行の探索型DocDD
imaimai17468
1
200
コーディングチェックの自動化がしたい!
imaimai17468
4
1.2k
型パズルを好きになるために、競プロを型システムだけで解いてみることにした
imaimai17468
6
820
フロントエンド設計の所感 1年目
imaimai17468
0
110
Silk Weave -未来研究大会発表資料-
imaimai17468
1
72
TailwindCSSで学ぶ技術批判の気をつけ方
imaimai17468
8
7.1k
Next.js+yjs+BlockNoteでNotionライクな最高の共同編集エディタを作ろう
imaimai17468
0
3.3k
BlockNoteを布教するぜ
imaimai17468
0
85
Featured
See All Featured
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
2
540
Self-Hosted WebAssembly Runtime for Runtime-Neutral Checkpoint/Restore in Edge–Cloud Continuum
chikuwait
0
800
Claude Code のすすめ
schroneko
67
230k
Kristin Tynski - Automating Marketing Tasks With AI
techseoconnect
PRO
0
520
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
133
19k
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
63
46k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
31
3.4k
Dominate Local Search Results - an insider guide to GBP, reviews, and Local SEO
greggifford
PRO
0
330
Unlocking the hidden potential of vector embeddings in international SEO
frankvandijk
0
940
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
1
320
A brief & incomplete history of UX Design for the World Wide Web: 1989–2019
jct
2
510
Six Lessons from altMBA
skipperchong
29
4.5k
Transcript
Next.jsでクエリパラメータを楽に扱おう nuqsを紹介! いまいまい 1
自己紹介 いまいまい (今井俊希) 株式会社ゆめみ 新卒 フロントエンドエンジニア 本編ではBlockNoteというライブラリで登壇 2
URLとクエリパラメータ、舐めたら死ぬ あぶない! <a href={`/hoge?huga=${piyo}&poyo=${fuga}`}>Link</a> URLを文字で扱うのは危険と言われがち URLクラスを使う URLSearchParamsクラスを使う 3
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
クエリパラメータ管理の課題 1. 複数のクエリパラメータを管理したいとき 一部だけ更新して、一部は維持とか 2. stateとの同期 inputなどの状態との同期 queryからstateへの初期状態反映 3. queryのバリデーション
4. AppRouter / ServerComponentsへの対応 5
nuqsについて紹介 next-usequerystateの略 発音は“nukes”. [njuks] Next.jsにおけるクエリパラメータを型安全かつ直感的に扱えるようにする 6
nuqsの使い方 ボタンの状態をqueryを同期させる inputのstateがリアルタイムにqueryに反映される const [name, setName] = useQueryState('name', parseAsString.withDefault("")) //
... return ( <input value={name} onChange={e => setName(e.target.value)} /> ) 7
豊富なparserの種類 string number (integer, float, hex) boolean literal (string, numeral)
enum date & timestamp array json (with zod scheme) なんなら自分で作れる (createParser) 8
複数の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
Option パーサーに複数のオプションを渡すことができる parseAsString.withOptions({ history: 'push' }) history // 履歴が置き換えられる useQueryState('foo',
{ history: 'replace' }) // 新しく履歴が追加される useQueryState('foo', { history: 'push' }) historyのhackはbad UXにつながる可能性があるので注意 10
shallow クエリパラメータの更新によるルーティング範囲の切り替え useQueryState('foo', { shallow: true }) true クライアントで完結 false
サーバーまで通知されて、場合によっては再レンダリングされる queryによって即座にfetchさせたい場合など ハードナビゲーション 11
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
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
2. ページロード時のsearchParamsと同期をとる clientでのuseQueryStateのsetを初期で行うイメージ export default function Page({ searchParams }: {
searchParams: Record<string, string | string[] | undefined> }) { const searchParamsCache.parse(searchParams) // ... } 14
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
蛇足 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
良いqueryライフを! 17