Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Introducing adapters for other frameworks #644

Merged
merged 37 commits into from
Oct 21, 2024
Merged

Conversation

franky47
Copy link
Member

@franky47 franky47 commented Sep 20, 2024

Tasks

  • Add docs on adapters in Fumadocs
  • Add/update docs on testing showcasing the NuqsTestingAdapter
  • Add docs on adapters in the readme
  • Update migration docs
  • Expose adapters API for users to create their own (marked as unstable in v2, stabilised after gathering feedback)
  • Remove the adapter for OneJS, as it pulls in a ton of dependencies for RN. It's simple enough to be a copy-pasta example integration to showcase the custom adapters API.

idea: Should the React adapter provide initial search params on the server for custom SSR implementations? -> Not on this version, can be an improvement later. Resources: Vite + React SSR

Add docs on how to create adapters (for external contributions) -> can be done in a later time as it's all experimental

Breaking changes

nuqs now requires wrapping your app with a NuqsAdapter (see below), which is a context provider connecting your framework APIs to the hooks' internals.

The startTransition option no longer automatically sets shallow: false.

The Options type is no longer generic.

  • The UseQueryStatesOptions is now a type rather than an interface, and is now
    generic over the type of the object you pass to useQueryStates.

The "use client" directive was not included in the client import (import {} from 'nuqs'). It has now been added, meaning that server-side code needs to import from nuqs/server to avoid errors like:

Error: Attempted to call withDefault() from the server but withDefault is on
the client. It's not possible to invoke a client function from the server, it can
only be rendered as a Component or passed to props of a Client
Component.

Adapters

You'll need to wrap your application in a NuqsAdapter, as such:

Next.js, app router:

// src/app/layout.tsx
import { NuqsAdapter } from 'nuqs/adapters/next/app'
import { type ReactNode } from 'react'

export default function RootLayout({
  children
}: {
  children: ReactNode
}) {
  return (
    <html>
      <body>
        <NuqsAdapter>{children}</NuqsAdapter>
      </body>
    </html>
  )
}

Next.js, pages router:

// src/pages/_app.tsx
import type { AppProps } from 'next/app'
import { NuqsAdapter } from 'nuqs/adapters/next/pages'

export default function MyApp({ Component, pageProps }: AppProps) {
  return (
    <NuqsAdapter>
      <Component {...pageProps} />
    </NuqsAdapter>
  )
}

The main reason for adapters is to open up nuqs to other React frameworks:

Vanilla React (eg: with Vite):

import { NuqsAdapter } from 'nuqs/adapters/react'

createRoot(document.getElementById('root')!).render(
  <NuqsAdapter>
    <App />
  </NuqsAdapter>
)

Remix:

// app/root.tsx
import { NuqsAdapter } from 'nuqs/adapters/remix'

// ...

export default function App() {
  return (
    <NuqsAdapter>
      <Outlet />
    </NuqsAdapter>
  )
}

React Router:

import { NuqsAdapter } from 'nuqs/adapters/react-router'
import { createBrowserRouter, RouterProvider } from 'react-router-dom'
import App from './App'

const router = createBrowserRouter([
  {
    path: '/',
    element: <App />
  }
])

export function ReactRouter() {
  return (
    <NuqsAdapter>
      <RouterProvider router={router} />
    </NuqsAdapter>
  )
}

Closes #603, #620.

Copy link

vercel bot commented Sep 20, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
nuqs ✅ Ready (Inspect) Visit Preview 💬 Add feedback Oct 21, 2024 8:58pm

Copy link

pkg-pr-new bot commented Sep 20, 2024

Open in Stackblitz

pnpm add https://pkg.pr.new/nuqs@644

commit: 35ce3f6

@franky47 franky47 mentioned this pull request Sep 24, 2024
@franky47 franky47 added this to the v2 milestone Sep 27, 2024
@franky47 franky47 mentioned this pull request Oct 3, 2024
13 tasks
@franky47 franky47 marked this pull request as ready for review October 7, 2024 21:32
@franky47 franky47 marked this pull request as draft October 8, 2024 08:59
BREAKING CHANGE: When using Next.js, nuqs v2 requires next@>=14.2.0.

Initially this was going to be >=14.1.2, but a bug fix in vercel/next.js#61419
that landed in 14.2.0 makes it that 14.1.{2,3,4} would require copying the
ReadOnlyURLSearchParams returned by useSearchParams to conform
to the adapters API.
Always test against Next.js releases that introduced changes
in the app router core, but not all the intermediary ones.
The stricter set can be tested on merge to next, before deployments,
and manually when using the uncached `ci` branch.
Don't test those at all in regular cases.
Ignoring tests for the build, but allow type-checking and injecting globals for Vitest.
BREAKING CHANGE: `UseQueryStatesOptions` is now generic over the key map
(the object containing parser definitions you pass to useQueryStates),
and is now a type rather than an interface.
@franky47 franky47 merged commit 8220127 into v2/release Oct 21, 2024
21 checks passed
@franky47 franky47 deleted the feat/adapters branch October 21, 2024 21:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant