mirror of
https://github.com/cloudflare/vinext.git
synced 2026-05-09 08:25:34 +02:00
[PR #689] [MERGED] fix: usePathname() returns "/" during SSR of "use client" page components #772
Labels
No labels
enhancement
enhancement
good first issue
help wanted
nextjs-tracking
nextjs-tracking
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/vinext#772
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/cloudflare/vinext/pull/689
Author: @Divkix
Created: 3/26/2026
Status: ✅ Merged
Merged: 3/26/2026
Merged by: @southpolesteve
Base:
main← Head:fix/usePathname-ssr-hydration-688📝 Commits (2)
6f4272afix: usePathname() returns "/" during SSR of "use client" page components (#688)978c48crefactor: deduplicate global accessor key and tighten types📊 Changes
6 files changed (+277 additions, -12 deletions)
View changed files
📝
packages/vinext/src/shims/navigation-state.ts(+14 -2)📝
packages/vinext/src/shims/navigation.ts(+48 -10)📝
tests/e2e/app-router/routes.spec.ts(+34 -0)➕
tests/fixtures/app-basic/app/use-client-page-pathname/[slug]/page.tsx(+23 -0)➕
tests/fixtures/app-basic/app/use-client-page-pathname/page.tsx(+28 -0)➕
tests/nextjs-compat/use-client-page-pathname.test.ts(+130 -0)📄 Description
Summary
Fixes #688.
usePathname()returns"/"during SSR when the page component itself is a"use client"component, causing a React hydration mismatchnavigation.tsfor the SSR entry vs"use client"components. The_registerStateAccessors()pattern only updates the SSR entry's instance — the"use client"instance falls back to_serverContext(null ->"/")navigation-state.tsnow also stores the ALS-backed accessor functions onglobalThisviaSymbol.for("vinext.navigation.globalAccessors"). The default accessors innavigation.tscheck this global before falling back to module-level state, ensuring all module instances reach the ALS-backed state regardless of which instance was registeredOn the browser (where
navigation-state.tsis never imported), the global key doesn't exist, so the fallback to module-level_serverContextis preserved — correct behavior for client-side hydration.Test plan
tests/nextjs-compat/use-client-page-pathname.test.ts— 8 tests coveringusePathname(),useSearchParams(),useParams()for"use client"page components (static + dynamic routes)tests/e2e/app-router/routes.spec.ts— 3 tests checking no hydration errors and correct rendering for"use client"pages🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.