[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"verticals":3,"article-url-as-state-manager":32,"code:tsx:true:1glkrvp":205,"code:tsx:true:1sqpodn":206,"code:tsx:true:1guqqvw":207},[4,20],{"id":5,"slug":6,"name":7,"tagline":8,"description":9,"accentFrom":10,"accentTo":11,"icon":12,"defaultLocale":13,"locales":14,"features":16,"position":19},"019fe637-3d33-714b-b57f-23e163ffca0c","dev","Web Development","Build. Learn. Ship.","Practical courses, engineering-grade articles and open-source tools for people who ship.","violet-500","cyan-400","◇","en",[13,15],"fa",{"courses":17,"paths":17,"articles":17,"exams":18,"flashcards":18,"packages":17,"community":17,"certificates":17,"teams":17,"commerce":17},true,false,0,{"id":21,"slug":22,"name":23,"tagline":24,"description":25,"accentFrom":26,"accentTo":10,"icon":27,"defaultLocale":13,"locales":28,"features":30,"position":31},"019fe637-3dc2-754c-8657-0f175bfee7c6","lang","Languages","Learn a language the way you learn a codebase.","Structured paths, listening drills and spaced repetition that actually sticks.","amber-400","⌘",[13,15,29],"es",{"courses":17,"paths":17,"articles":18,"exams":18,"flashcards":18,"packages":18,"community":17,"certificates":18,"teams":18,"commerce":17},2,{"id":33,"slug":34,"title":35,"subtitle":36,"excerpt":37,"coverUrl":38,"locale":13,"readingMinutes":39,"publishedAt":40,"viewCount":41,"likeCount":19,"commentCount":19,"author":42,"vertical":47,"topic":48,"tags":51,"_count":63,"playground":36,"body":64,"bodyMd":196,"seo":197,"translationGroupId":199,"thread":200,"assessments":202,"translations":203,"quiz":36},"019fe65f-b9de-72a8-8656-ee81360dbd99","url-as-state-manager","The URL Is Your Best State Manager",null,"You're storing filter state, search queries, and pagination in useState — and losing it every time someone refreshes. The URL already does this better.","\u002Fmedia\u002Fcovers\u002Furl-as-state-manager.png",4,"2026-06-29T07:59:09.726Z",3,{"id":43,"name":44,"username":45,"avatarUrl":36,"headline":46},"019fe637-3c25-7088-9034-39c9f15dc3c8","Parsa Jiravand","parsa","Frontend engineer · building bestpractic",{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":49,"name":50},"javascript","JavaScript",[52,55,58,60],{"slug":53,"name":54,"color":36},"webdev","Webdev",{"slug":56,"name":57,"color":36},"frontend","Frontend",{"slug":49,"name":59,"color":36},"Javascript",{"slug":61,"name":62,"color":36},"react","React",{"assessments":19},{"blocks":65,"version":195},[66,70,73,77,80,112,115,118,121,128,131,134,137,143,147,150,153,157,160,163,166,169,172,175,178,181,184,187],{"id":67,"html":68,"type":69},"b1","\u003Cp>There&#39;s a category of bug I see in almost every SPA I touch: the user applies a filter, sorts a table, pages through results — and then refreshes, or pastes the link to a colleague, and all of it is gone. The bug report says &quot;it doesn&#39;t remember my state.&quot; The root cause is almost always the same: that state lived in \u003Ccode>useState\u003C\u002Fcode>, when it should have lived in the URL.\u003C\u002Fp>","paragraph",{"id":71,"html":72,"type":69},"b2","\u003Cp>This is a mental model, not a framework feature. It applies equally in React, Vue, Svelte, or plain JS. The URL is a state management primitive you already have — built into every browser, shared for free — and most frontend teams underuse it.\u003C\u002Fp>",{"id":74,"html":75,"text":75,"type":76,"level":31},"b3","What belongs in the URL","heading",{"id":78,"html":79,"type":69},"b4","\u003Cp>Not all state belongs there. The key question is: \u003Cstrong>would a user want to share or bookmark this?\u003C\u002Fstrong>\u003C\u002Fp>",{"id":81,"head":82,"rows":86,"type":111},"b5",[83,84,85],"State","URL?","Why",[87,91,94,97,100,104,107],[88,89,90],"Active tab \u002F current view","Yes","Direct-linkable, shareable",[92,89,93],"Search query","Back button works, shareable",[95,89,96],"Filters, sort order","Reproducible results",[98,89,99],"Pagination cursor","&quot;Send me the page you&#39;re on&quot;",[101,102,103],"Form draft in progress","No","Ephemeral, user-session only",[105,102,106],"Hover state, tooltip open","Ephemeral UI state",[108,109,110],"Auth tokens","Never","Security hazard","table",{"id":113,"html":114,"type":69},"b6","\u003Cp>The filter and the modal-open state are both &quot;UI state,&quot; but they&#39;re different in kind. One the user would share; one they wouldn&#39;t. Put the first in the URL and leave the second in component state.\u003C\u002Fp>",{"id":116,"html":117,"text":117,"type":76,"level":31},"b7","What you gain for free",{"id":119,"html":120,"type":69},"b8","\u003Cp>When search\u002Ffilter\u002Fsort state lives in the URL, you get three things without writing a single extra line of code:\u003C\u002Fp>",{"id":122,"type":123,"items":124,"ordered":17},"b9","list",[125,126,127],"\u003Cstrong>Refresh survival.\u003C\u002Fstrong> The user filters a table, refreshes — the filter is still there.","\u003Cstrong>Shareable links.\u003C\u002Fstrong> &quot;Here&#39;s what I&#39;m looking at&quot; works via copy-paste.","\u003Cstrong>Browser history.\u003C\u002Fstrong> Back and forward navigate state transitions, which is what users expect.",{"id":129,"html":130,"type":69},"b10","\u003Cp>These are not small wins. &quot;Back button broke my filters&quot; is a real UX bug, and moving to URL state fixes it completely and permanently.\u003C\u002Fp>",{"id":132,"html":133,"text":133,"type":76,"level":31},"b11","The pattern in React",{"id":135,"html":136,"type":69},"b12","\u003Cp>Here&#39;s the before\u002Fafter for a search input:\u003C\u002Fp>",{"id":138,"code":139,"type":140,"language":141,"highlight":142},"b13","\u002F\u002F Before: state dies on refresh\nfunction SearchPage() {\n  const [query, setQuery] = useState(\"\");\n  return (\n    \u003Cinput\n      value={query}\n      onChange={e => setQuery(e.target.value)}\n    \u002F>\n  );\n}","code","tsx",[],{"id":144,"code":145,"type":140,"language":141,"highlight":146},"b14","\u002F\u002F After: state lives in the URL\nimport { useSearchParams } from \"react-router-dom\"; \u002F\u002F or Next.js's useSearchParams\n\nfunction SearchPage() {\n  const [params, setParams] = useSearchParams();\n  const query = params.get(\"q\") ?? \"\";\n\n  return (\n    \u003Cinput\n      value={query}\n      onChange={e =>\n        setParams(p => { p.set(\"q\", e.target.value); return p; })\n      }\n    \u002F>\n  );\n}",[],{"id":148,"html":149,"type":69},"b15","\u003Cp>The component is roughly the same size. The URL is now \u003Ccode>?q=typescript\u003C\u002Fcode>. Refresh — still there. Copy the URL — the recipient sees the same results. The back button undoes the last keystroke (or use \u003Ccode>replace\u003C\u002Fcode> instead of \u003Ccode>push\u003C\u002Fcode> to keep history clean for every keystroke).\u003C\u002Fp>",{"id":151,"html":152,"type":69},"b16","\u003Cp>For more complex state — multiple filters, sort columns, numeric values — a library like \u003Ca href=\"https:\u002F\u002Fnuqs.47ng.com\u002F\">nuqs\u003C\u002Fa> handles serialization, type coercion, and history mode in a \u003Ccode>useState\u003C\u002Fcode>-compatible API:\u003C\u002Fp>",{"id":154,"code":155,"type":140,"language":141,"highlight":156},"b17","import { useQueryState, parseAsInteger } from \"nuqs\";\n\nconst [sort, setSort] = useQueryState(\"sort\", { defaultValue: \"date\" });\nconst [page, setPage] = useQueryState(\"page\", parseAsInteger.withDefault(1));",[],{"id":158,"html":159,"type":69},"b18","\u003Cp>Typed URL params, familiar API, zero custom serialization logic.\u003C\u002Fp>",{"id":161,"html":162,"text":162,"type":76,"level":31},"b19","The failure mode to watch for",{"id":164,"html":165,"type":69},"b20","\u003Cp>Don&#39;t put too much in the URL. It&#39;s for state the user would meaningfully share — not for every piece of transient UI. A deeply nested JSON blob in a query string is the wrong answer. Keep it flat, keep it readable.\u003C\u002Fp>",{"id":167,"html":168,"type":69},"b21","\u003Cp>\u003Ccode>?status=active&amp;sort=name&amp;page=2\u003C\u002Fcode> is good. \u003Ccode>?state=eyJzdGF0dXMiOiJhY3RpdmUi...\u003C\u002Fcode> is a red flag.\u003C\u002Fp>",{"id":170,"html":171,"type":69},"b22","\u003Cp>If your state is too complex to flatten into a few readable params, it may genuinely belong in a database or session store, not the URL. The URL should be a \u003Cem>narrow\u003C\u002Fem> representation of &quot;what the user is looking at&quot; — not a full snapshot of the app.\u003C\u002Fp>",{"id":173,"html":174,"text":174,"type":76,"level":31},"b23","The takeaway",{"id":176,"html":177,"type":69},"b24","\u003Cp>The URL is a first-class state management layer that every browser already implements, every user already understands, and most SPAs leave mostly unused. Before you reach for \u003Ccode>useState\u003C\u002Fcode>, ask: would the user want to share or bookmark this? If yes, put it in the URL — you get refresh survival, deep links, and a working back button for free.\u003C\u002Fp>",{"id":179,"html":180,"type":69},"b25","\u003Cp>That&#39;s not a third-party library or a framework feature. It&#39;s how the web was designed. Use it.\u003C\u002Fp>",{"id":182,"type":183},"b26","divider",{"id":185,"html":186,"type":69},"b27","\u003Cp>\u003Cem>Thanks for reading! Let&#39;s stay connected:\u003C\u002Fem>\u003C\u002Fp>",{"id":188,"type":123,"items":189,"ordered":18},"b28",[190,191,192,193,194],"⭐ \u003Cstrong>GitHub\u003C\u002Fstrong> — follow me and star the projects: \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fparsajiravand\">github.com\u002Fparsajiravand\u003C\u002Fa>","💬 \u003Cstrong>Discord\u003C\u002Fstrong> — join the frontend best-practices community: \u003Ca href=\"https:\u002F\u002Fdiscord.gg\u002Fd9KRhuAwQ\">discord.gg\u002Fd9KRhuAwQ\u003C\u002Fa>","📸 \u003Cstrong>Instagram\u003C\u002Fstrong> — frontend best practices, daily: \u003Ca href=\"https:\u002F\u002Fwww.instagram.com\u002Fbestpractice___\u002F\">@bestpractice___\u003C\u002Fa>","💼 \u003Cstrong>LinkedIn\u003C\u002Fstrong> — \u003Ca href=\"https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fparsa-jiravand\u002F\">linkedin.com\u002Fin\u002Fparsa-jiravand\u003C\u002Fa>","✉️ \u003Cstrong>Email\u003C\u002Fstrong> (work &amp; contract inquiries): \u003Ca href=\"mailto:bestpractice2026@gmail.com\">bestpractice2026@gmail.com\u003C\u002Fa>",1,"There's a category of bug I see in almost every SPA I touch: the user applies a filter, sorts a table, pages through results — and then refreshes, or pastes the link to a colleague, and all of it is gone. The bug report says \"it doesn't remember my state.\" The root cause is almost always the same: that state lived in `useState`, when it should have lived in the URL.\n\nThis is a mental model, not a framework feature. It applies equally in React, Vue, Svelte, or plain JS. The URL is a state management primitive you already have — built into every browser, shared for free — and most frontend teams underuse it.\n\n## What belongs in the URL\n\nNot all state belongs there. The key question is: **would a user want to share or bookmark this?**\n\n| State | URL? | Why |\n|---|---|---|\n| Active tab \u002F current view | Yes | Direct-linkable, shareable |\n| Search query | Yes | Back button works, shareable |\n| Filters, sort order | Yes | Reproducible results |\n| Pagination cursor | Yes | \"Send me the page you're on\" |\n| Form draft in progress | No | Ephemeral, user-session only |\n| Hover state, tooltip open | No | Ephemeral UI state |\n| Auth tokens | Never | Security hazard |\n\nThe filter and the modal-open state are both \"UI state,\" but they're different in kind. One the user would share; one they wouldn't. Put the first in the URL and leave the second in component state.\n\n## What you gain for free\n\nWhen search\u002Ffilter\u002Fsort state lives in the URL, you get three things without writing a single extra line of code:\n\n1. **Refresh survival.** The user filters a table, refreshes — the filter is still there.\n2. **Shareable links.** \"Here's what I'm looking at\" works via copy-paste.\n3. **Browser history.** Back and forward navigate state transitions, which is what users expect.\n\nThese are not small wins. \"Back button broke my filters\" is a real UX bug, and moving to URL state fixes it completely and permanently.\n\n## The pattern in React\n\nHere's the before\u002Fafter for a search input:\n\n```tsx\n\u002F\u002F Before: state dies on refresh\nfunction SearchPage() {\n  const [query, setQuery] = useState(\"\");\n  return (\n    \u003Cinput\n      value={query}\n      onChange={e => setQuery(e.target.value)}\n    \u002F>\n  );\n}\n```\n\n```tsx\n\u002F\u002F After: state lives in the URL\nimport { useSearchParams } from \"react-router-dom\"; \u002F\u002F or Next.js's useSearchParams\n\nfunction SearchPage() {\n  const [params, setParams] = useSearchParams();\n  const query = params.get(\"q\") ?? \"\";\n\n  return (\n    \u003Cinput\n      value={query}\n      onChange={e =>\n        setParams(p => { p.set(\"q\", e.target.value); return p; })\n      }\n    \u002F>\n  );\n}\n```\n\nThe component is roughly the same size. The URL is now `?q=typescript`. Refresh — still there. Copy the URL — the recipient sees the same results. The back button undoes the last keystroke (or use `replace` instead of `push` to keep history clean for every keystroke).\n\nFor more complex state — multiple filters, sort columns, numeric values — a library like [nuqs](https:\u002F\u002Fnuqs.47ng.com\u002F) handles serialization, type coercion, and history mode in a `useState`-compatible API:\n\n```tsx\nimport { useQueryState, parseAsInteger } from \"nuqs\";\n\nconst [sort, setSort] = useQueryState(\"sort\", { defaultValue: \"date\" });\nconst [page, setPage] = useQueryState(\"page\", parseAsInteger.withDefault(1));\n```\n\nTyped URL params, familiar API, zero custom serialization logic.\n\n## The failure mode to watch for\n\nDon't put too much in the URL. It's for state the user would meaningfully share — not for every piece of transient UI. A deeply nested JSON blob in a query string is the wrong answer. Keep it flat, keep it readable.\n\n`?status=active&sort=name&page=2` is good. `?state=eyJzdGF0dXMiOiJhY3RpdmUi...` is a red flag.\n\nIf your state is too complex to flatten into a few readable params, it may genuinely belong in a database or session store, not the URL. The URL should be a *narrow* representation of \"what the user is looking at\" — not a full snapshot of the app.\n\n## The takeaway\n\nThe URL is a first-class state management layer that every browser already implements, every user already understands, and most SPAs leave mostly unused. Before you reach for `useState`, ask: would the user want to share or bookmark this? If yes, put it in the URL — you get refresh survival, deep links, and a working back button for free.\n\nThat's not a third-party library or a framework feature. It's how the web was designed. Use it.\n\n---\n\n*Thanks for reading! Let's stay connected:*\n\n- ⭐ **GitHub** — follow me and star the projects: [github.com\u002Fparsajiravand](https:\u002F\u002Fgithub.com\u002Fparsajiravand)\n- 💬 **Discord** — join the frontend best-practices community: [discord.gg\u002Fd9KRhuAwQ](https:\u002F\u002Fdiscord.gg\u002Fd9KRhuAwQ)\n- 📸 **Instagram** — frontend best practices, daily: [@bestpractice___](https:\u002F\u002Fwww.instagram.com\u002Fbestpractice___\u002F)\n- 💼 **LinkedIn** — [linkedin.com\u002Fin\u002Fparsa-jiravand](https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fparsa-jiravand\u002F)\n- ✉️ **Email** (work & contract inquiries): [bestpractice2026@gmail.com](mailto:bestpractice2026@gmail.com)",{"title":35,"canonical":198,"description":37},"https:\u002F\u002Fbestpractic.org\u002Fblog\u002Furl-as-state-manager","019fe65f-b9de-72a8-8656-f174adb20a84",{"id":201,"locked":18},"019fe65f-c0c9-7232-b558-b2e784624917",[],[204],{"locale":13,"slug":34},"\u003Cdiv class=\"shj shj-lang-tsx shj-multiline\" data-lang=\"tsx\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003Cdiv>6\u003C\u002Fdiv>\u003Cdiv>7\u003C\u002Fdiv>\u003Cdiv>8\u003C\u002Fdiv>\u003Cdiv>9\u003C\u002Fdiv>\u003Cdiv>10\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-cmnt\">\u002F\u002F Before: state dies on refresh\n\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">function\u003C\u002Fspan> \u003Cspan class=\"shj-class\">SearchPage\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n  \u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>query\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> setQuery\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-func\">useState\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">\"\"\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n  \u003Cspan class=\"shj-kwd\">return\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\n    \u003Cspan class=\"shj-var\">\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&lt;\u003C\u002Fspan>\u003Cspan class=\"shj-var\">input\u003C\u002Fspan>\n      \u003Cspan class=\"shj-class\">value\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">={\u003C\u002Fspan>query\u003Cspan class=\"shj-oper\">}\u003C\u002Fspan>\n      \u003Cspan class=\"shj-class\">onChange\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">={\u003C\u002Fspan>e \u003Cspan class=\"shj-kwd\">=&gt;\u003C\u002Fspan> \u003Cspan class=\"shj-func\">setQuery\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>e\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>target\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>value\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">}\u003C\u002Fspan>\n    \u003Cspan class=\"shj-oper\">\u002F&gt;\u003C\u002Fspan>\n  \u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-tsx shj-multiline\" data-lang=\"tsx\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003Cdiv>6\u003C\u002Fdiv>\u003Cdiv>7\u003C\u002Fdiv>\u003Cdiv>8\u003C\u002Fdiv>\u003Cdiv>9\u003C\u002Fdiv>\u003Cdiv>10\u003C\u002Fdiv>\u003Cdiv>11\u003C\u002Fdiv>\u003Cdiv>12\u003C\u002Fdiv>\u003Cdiv>13\u003C\u002Fdiv>\u003Cdiv>14\u003C\u002Fdiv>\u003Cdiv>15\u003C\u002Fdiv>\u003Cdiv>16\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-cmnt\">\u002F\u002F After: state lives in the URL\n\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">import\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> useSearchParams \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">from\u003C\u002Fspan> \u003Cspan class=\"shj-str\">\"react-router-dom\"\u003C\u002Fspan>; \u003Cspan class=\"shj-cmnt\">\u002F\u002F or Next.js's useSearchParams\n\u003C\u002Fspan>\n\u003Cspan class=\"shj-kwd\">function\u003C\u002Fspan> \u003Cspan class=\"shj-class\">SearchPage\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n  \u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>params\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> setParams\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-func\">useSearchParams\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n  \u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> query \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> params\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">get\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">\"q\"\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">??\u003C\u002Fspan> \u003Cspan class=\"shj-str\">\"\"\u003C\u002Fspan>;\n\n  \u003Cspan class=\"shj-kwd\">return\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\n    \u003Cspan class=\"shj-var\">\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&lt;\u003C\u002Fspan>\u003Cspan class=\"shj-var\">input\u003C\u002Fspan>\n      \u003Cspan class=\"shj-class\">value\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">={\u003C\u002Fspan>query\u003Cspan class=\"shj-oper\">}\u003C\u002Fspan>\n      \u003Cspan class=\"shj-class\">onChange\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">={\u003C\u002Fspan>e \u003Cspan class=\"shj-kwd\">=&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"shj-func\">setParams\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>p \u003Cspan class=\"shj-kwd\">=&gt;\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> p\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">set\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">\"q\"\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> e\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>target\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>value\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>; \u003Cspan class=\"shj-kwd\">return\u003C\u002Fspan> p; \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\n      \u003Cspan class=\"shj-oper\">}\u003C\u002Fspan>\n    \u003Cspan class=\"shj-oper\">\u002F&gt;\u003C\u002Fspan>\n  \u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-tsx shj-multiline\" data-lang=\"tsx\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-kwd\">import\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> useQueryState\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> parseAsInteger \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">from\u003C\u002Fspan> \u003Cspan class=\"shj-str\">\"nuqs\"\u003C\u002Fspan>;\n\n\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>sort\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> setSort\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-func\">useQueryState\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">\"sort\"\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> defaultValue\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-str\">\"date\"\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>page\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> setPage\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-func\">useQueryState\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">\"page\"\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> parseAsInteger\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">withDefault\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-num\">1\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>"]