fix: Upgrade nuqs to 2.9.2 before the shared table hook lands - #374
Conversation
nuqs 2.9.0 and 2.9.1 carry an upstream bug (nuqs#1501) where useQueryState(s) permanently desyncs from the URL after React discards a render. The repo uses the React Router v7 adapter on React 19 — the affected configuration — and SeriesTable is the only nuqs consumer, so the Library page's sort, filter and pagination state was exposed. 2.9.2 fixes it with a three-line render-phase recovery in useQueryStates. Verified against a production build in Chrome: paging, sort change, filter change, search, back/forward across a route change, and a deep-linked reload all keep the rendered table in step with the URL. Resolves the ticket "Upgrade nuqs to ^2.9.2 before the shared hook lands" (#368), unblocking the pagination decision on the useTableState map (#353). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Et1eFmQyJUBncfpsWWvSJC
🦋 Changeset detectedLatest commit: 31c4136 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
📝 WalkthroughWalkthroughUpdates Changesnuqs dependency upgrade
Estimated code review effort: 1 (Trivial) | ~2 minutes Possibly related issues
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint install failed. For unrecoverable errors, disable the tool in CodeRabbit configuration. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@frontend/package.json`:
- Line 43: Regenerate frontend/package-lock.json after updating the nuqs
dependency in frontend/package.json, ensuring it reflects the new ^2.9.2
resolution, then include the updated lockfile in the change so npm ci uses the
committed dependency graph.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 67840cda-6fa7-48ee-bbd4-d93f58f1cb66
⛔ Files ignored due to path filters (1)
frontend/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (2)
.changeset/upgrade-nuqs-to-2-9-2.mdfrontend/package.json
|
@coderabbitai the lockfile is already regenerated and included in this PR — It was produced by No change needed. |
|
Tip For best results, initiate chat on the files or code changes.
|
Resolves #368, unblocking #360 on the useTableState map.
Why
nuqs2.9.0 and 2.9.1 carry an upstream bug (nuqs#1501) whereuseQueryState(s)permanently desyncs from the URL after React discards a render. It is fixed in 2.9.2.This repo was on the affected configuration, not just an affected version:
src/App.tsx:10importsNuqsAdapterfromnuqs/adapters/react-router/v7on React 19, andSeriesTable.tsxis the only nuqs consumer — so the blast radius was the Library page's sort, filter and pagination state.The fix is three lines in nuqs' own
useQueryStates.ts(nuqs#1502): a render-phase recovery when the mirroredinternalStatedrifts from the authoritativestateRef.current.What changed
frontend/package.json^2.9.0→^2.9.2, and the lockfile follows.Raising the declared floor rather than only moving the lock is deliberate — it stops a fresh
npm installresolving back onto 2.9.0/2.9.1. The only other lockfile movement is nuqs' own dependency@standard-schema/spec1.0.0 → 1.1.0, which dedupes against the copy vitest already pulled in. No source changes.Verification
npm run lintclean;npm --prefix frontend test141/141 across 27 files; production build succeeds.Beyond that, a manual pass against a production build in Chrome, since the existing tests do not cover the back/forward path. The real database holds one series, so pagination was not exercisable against it; the production build was served behind a throwaway proxy forwarding to the live backend for real auth, overriding only
GET /api/serieswith 63 synthetic rows. Data synthetic; router, adapter, build and browser real.page=1?sort=ComicName.asc,pagedropped in the same writepage=1pagedropped, sort preserved, only paused rowspage=1?search=Marvel,pagedropped — the mixed 300ms/50ms batch collapses correctlyhistory.lengthnever grew, confirminghistory: "replace"is not being escalated by a batched key.Notes for the map
dist/rather than the changelog: the three batching rules are byte-identical and the synchronousemitter.emitis unchanged, so the shared hook'ssetParams({ sort, page: null })plan is unaffected. Two findings get stronger — 2.9.1 #1480 makeslimitUrlUpdatesprecedence true in code and not merely in the docs, and #1469 reinforces the single-emitter premise. This also discharges Is the nuqs shadow-state dance still necessary on nuqs 2.9? #356's owed production-build caveat./library?page=2renders page 0 and stripspage, because the clamp atSeriesTable.tsx:267-276runs whiledatais still empty. A/B'd againstnuqs@2.9.0on the same build with the same data — identical wrong result, so it is neither caused nor fixed by this bump. Left untouched here so a regression has one obvious suspect; filed as Decide where the deep-linked-page clamp fix ships #372.🤖 Generated with Claude Code
https://claude.ai/code/session_01Et1eFmQyJUBncfpsWWvSJC
Summary by CodeRabbit