diff --git a/errors/NUQS-303.md b/errors/NUQS-303.md new file mode 100644 index 000000000..4ae69ff4a --- /dev/null +++ b/errors/NUQS-303.md @@ -0,0 +1,17 @@ +# Multiple adapter contexts detected + +## Probable cause + +This error occurs in [debug mode](https://nuqs.47ng.com/docs/debugging) in +certain monorepo setups where references of the adapter context aren't the same +in different packages, and cause a [`NUQS-404 - nuqs requires an adapter to work with your framework`](./NUQS-404) error. + +## Root cause + +As described in the [React docs](https://react.dev/reference/react/useContext#my-component-doesnt-see-the-value-from-my-provider), this can happen with Context providers (which +is what adapters are) being re-created in different modules and causing different +references being used for a provider and consumers. + +## Possible solutions + +See issue [#798](https://github.com/47ng/nuqs/issues/798) for more details. diff --git a/packages/nuqs/src/adapters/lib/context.ts b/packages/nuqs/src/adapters/lib/context.ts index 034fa773a..33ee54d44 100644 --- a/packages/nuqs/src/adapters/lib/context.ts +++ b/packages/nuqs/src/adapters/lib/context.ts @@ -1,4 +1,5 @@ import { createContext, createElement, useContext, type ReactNode } from 'react' +import { debugEnabled } from '../../debug' import { error } from '../../errors' import type { UseAdapterHook } from './defs' @@ -13,6 +14,19 @@ export const context = createContext({ }) context.displayName = 'NuqsAdapterContext' +declare global { + interface Window { + __NuqsAdapterContext?: typeof context + } +} + +if (debugEnabled && typeof window !== 'undefined') { + if (window.__NuqsAdapterContext && window.__NuqsAdapterContext !== context) { + console.error(error(303)) + } + window.__NuqsAdapterContext = context +} + /** * Create a custom adapter (context provider) for nuqs to work with your framework / router. * diff --git a/packages/nuqs/src/debug.ts b/packages/nuqs/src/debug.ts index 70fc27af8..4d4fa1ca3 100644 --- a/packages/nuqs/src/debug.ts +++ b/packages/nuqs/src/debug.ts @@ -1,7 +1,7 @@ -const enabled = isDebugEnabled() +export const debugEnabled = isDebugEnabled() export function debug(message: string, ...args: any[]) { - if (!enabled) { + if (!debugEnabled) { return } const msg = sprintf(message, ...args) @@ -10,7 +10,7 @@ export function debug(message: string, ...args: any[]) { } export function warn(message: string, ...args: any[]) { - if (!enabled) { + if (!debugEnabled) { return } console.warn(message, ...args) diff --git a/packages/nuqs/src/errors.ts b/packages/nuqs/src/errors.ts index 072794769..a7fe9ca6e 100644 --- a/packages/nuqs/src/errors.ts +++ b/packages/nuqs/src/errors.ts @@ -1,4 +1,5 @@ export const errors = { + 303: 'Multiple adapter contexts detected. This might happen in monorepos.', 404: 'nuqs requires an adapter to work with your framework.', 409: 'Multiple versions of the library are loaded. This may lead to unexpected behavior. Currently using `%s`, but `%s` (via the %s adapter) was about to load on top.', 414: 'Max safe URL length exceeded. Some browsers may not be able to accept this URL. Consider limiting the amount of state stored in the URL.',