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
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
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
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
31
3.4k
JAMstack: Web Apps at Ludicrous Speed - All Things Open 2022
reverentgeek
1
600
Facilitating Awesome Meetings
lara
57
7.1k
How To Speak Unicorn (iThemes Webinar)
marktimemedia
1
580
Why Mistakes Are the Best Teachers: Turning Failure into a Pathway for Growth
auna
0
280
SEO for Brand Visibility & Recognition
aleyda
0
4.7k
Optimising Largest Contentful Paint
csswizardry
37
4k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
230
23k
We Have a Design System, Now What?
morganepeng
55
8.3k
Design in an AI World
tapps
1
320
The Limits of Empathy - UXLibs8
cassininazir
1
670
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
11
1k
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