Skip to content

NuqsTestingAdapter: queued URL updates are flushed before dependent components mount #1331

@iulspop

Description

@iulspop

Bug Description

When using NuqsTestingAdapter in Storybook stories, queued URL updates set by one component are flushed (cleared) before React mounts sibling/child components that depend on the updated query parameter. This causes the dependent component to initialize with null instead of the queued value.

Reproduction

We have a Storybook story where a state machine transitions from a "triage drawer" to a "fix drawer":

  1. The triage drawer is opened via NuqsTestingAdapter's initial searchParams={{ 'triage-finding-id': 'finding-1' }}
  2. During the triage flow, the state machine calls setFindingFixFindingId('finding-1') via useQueryState('fix-finding-id')
  3. This queues a URL update for fix-finding-id
  4. On the next render, NuqsTestingAdapter flushes the update queue (resets it), before the fix drawer component mounts
  5. The fix drawer's useQueryState('fix-finding-id') initializes with null instead of 'finding-1'

Current Workaround

Setting resetUrlUpdateQueueOnMount={false} on NuqsTestingAdapter prevents the queue from being cleared, allowing the fix drawer to read the queued value:

<NuqsTestingAdapter
  searchParams={{ 'triage-finding-id': FINDING_ID }}
  resetUrlUpdateQueueOnMount={false}
>
  <Story />
</NuqsTestingAdapter>

However, this prop feels like a band-aid over a timing issue rather than a proper solution.

Better Alternative

We switched to using NuqsAdapter from nuqs/adapters/react-router/v7 (with storybook-addon-remix-react-router providing the React Router context) and setting initial search params via React Router's location.searchParams in the story parameters. This works correctly because nuqs reads/writes through React Router's state, which doesn't have the queue/flush timing issue.

// Decorator
<NuqsAdapter>
  <Story />
</NuqsAdapter>

// Story parameters
parameters: {
  reactRouter: {
    location: {
      searchParams: { 'triage-finding-id': FINDING_ID },
    },
  },
},

Expected Behavior

NuqsTestingAdapter should not flush queued URL updates before all dependent components have had a chance to mount and read the queued values. The queue should be drained in a way that respects React's rendering lifecycle.

Environment

  • nuqs: ^2.4.3
  • React: 19.1.1
  • Storybook: 8.x
  • React Router: ^7.12.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions