Skip to content

Commit

Permalink
feat: Detect multiple contexts loaded at the same time
Browse files Browse the repository at this point in the history
  • Loading branch information
franky47 committed Feb 1, 2025
1 parent 2f1220c commit d332d00
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 3 deletions.
17 changes: 17 additions & 0 deletions errors/NUQS-303.md
Original file line number Diff line number Diff line change
@@ -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.
14 changes: 14 additions & 0 deletions packages/nuqs/src/adapters/lib/context.ts
Original file line number Diff line number Diff line change
@@ -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'

Expand All @@ -13,6 +14,19 @@ export const context = createContext<AdapterContext>({
})
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.
*
Expand Down
6 changes: 3 additions & 3 deletions packages/nuqs/src/debug.ts
Original file line number Diff line number Diff line change
@@ -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)
Expand All @@ -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)
Expand Down
1 change: 1 addition & 0 deletions packages/nuqs/src/errors.ts
Original file line number Diff line number Diff line change
@@ -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.',
Expand Down

0 comments on commit d332d00

Please sign in to comment.