|
| 1 | +--- |
| 2 | +title: Waku |
| 3 | +description: Integrate nuqs with Waku |
| 4 | +--- |
| 5 | + |
| 6 | +[Waku](https://waku.gg/) is supported as a community-contributed adapter. |
| 7 | + |
| 8 | +## Step 1: Add the adapter code |
| 9 | + |
| 10 | +<Callout type="warn"> |
| 11 | + The custom adapters APIs are not yet stable and may change in the future |
| 12 | + in a minor or patch release (not following SemVer). |
| 13 | +</Callout> |
| 14 | + |
| 15 | +```tsx title="app/nuqs-waku-adapter.tsx" |
| 16 | +"use client"; |
| 17 | + |
| 18 | +import { |
| 19 | + type unstable_AdapterOptions as AdapterOptions, |
| 20 | + unstable_createAdapterProvider as createAdapterProvider, |
| 21 | + renderQueryString, |
| 22 | +} from "nuqs/adapters/custom"; |
| 23 | +import { useRouter_UNSTABLE as useRouter } from "waku"; |
| 24 | + |
| 25 | +function useNuqsAdapter() { |
| 26 | + const { path, query, push, replace } = useRouter(); |
| 27 | + const searchParams = new URLSearchParams(query); |
| 28 | + const updateUrl = (search: URLSearchParams, options: AdapterOptions) => { |
| 29 | + const query = renderQueryString(search); |
| 30 | + const url = path + query + location.hash; |
| 31 | + if (options.shallow) { |
| 32 | + options.history === "push" |
| 33 | + ? history.pushState(null, "", url) |
| 34 | + : history.replaceState(null, "", url); |
| 35 | + } else { |
| 36 | + const updateMethod = options.history === "push" ? push : replace; |
| 37 | + // bypass waku's typesafe route check by using `as never` |
| 38 | + updateMethod(url as never); |
| 39 | + } |
| 40 | + // Waku router does not scroll unless the pathname changes |
| 41 | + if (options.scroll) { |
| 42 | + window.scrollTo(0, 0); |
| 43 | + } |
| 44 | + }; |
| 45 | + return { |
| 46 | + searchParams, |
| 47 | + updateUrl, |
| 48 | + }; |
| 49 | +} |
| 50 | + |
| 51 | +export const NuqsAdapter = createAdapterProvider(useNuqsAdapter); |
| 52 | + |
| 53 | +``` |
| 54 | + |
| 55 | +## Step 2: wrap your root layout |
| 56 | + |
| 57 | +Integrate the adapter into a _layout.tsx or _root.tsx file, by wrapping the `{children}` |
| 58 | +component: |
| 59 | + |
| 60 | +```tsx title="app/_layout.tsx" /NuqsAdapter/ |
| 61 | +import { Suspense, type ReactNode } from 'react'; |
| 62 | + |
| 63 | +import { NuqsAdapter } from './nuqs-waku-adapter' |
| 64 | + |
| 65 | +type LayoutProps = { children: ReactNode }; |
| 66 | + |
| 67 | +export default async function Layout({ children }: LayoutProps) { |
| 68 | + return ( |
| 69 | + <> |
| 70 | + <NuqsAdapter> |
| 71 | + <Suspense> |
| 72 | + {children} |
| 73 | + </Suspense> |
| 74 | + </NuqsAdapter> |
| 75 | + </> |
| 76 | + ); |
| 77 | +} |
| 78 | + |
| 79 | +export const getConfig = async () => { |
| 80 | + return { |
| 81 | + render: 'dynamic', |
| 82 | + // render: 'static', // works but can cause hydration warnings |
| 83 | + } as const; |
| 84 | +}; |
| 85 | +``` |
0 commit comments