Files
4395d7c807 Fix repeated navigations while the Instant Navigation lock is held (#95864)
With the Instant Navigation Testing lock held (the Navigation Inspector
paused), repeated client navigations between pages that share a layout
could sometimes get stuck without ever resolving.

The root cause turned out to be a subtle problem with the client
router's use of `useDeferredValue` to switch between the cached UI and
the final UI. The mechanism only works as we intend when mounting a new
part of the tree. When updating an existing part of the tree, like a
shared layout, React will skip the cached UI entirely.

We were already aware of this issue with the `useDeferredValue`
approach. The plan is to instead model cached navigation as an
optimistic update followed by a transition update. Before we can make
such a change, though, we need to make a change in React to allow
optimistic updates to suspend (currently, optimistic updates act like
sync updates, and can trigger existing Suspense boundaries to switch
back to their fallback state).

To workaround this issue when using the Navigation Inspector, we're
going to change how the inspector works when multiple navigations are
performed during the same "lock". Instead of keeping the entire sequence
blocked until the end, we will instead only block the most recent one.
This more closely matches what the inspector UI implies, anyway: it
doesn't show a stack of pending navigations, only the most recent one.

This doesn't absolve us from needing to switch to using an optimistic
update. That's needed regardless to address similar behavior in
production. But this sidesteps the issue for now, and we were planning
to make this change to the Navigation Inspector regardless.

Co-authored-by: Sam Selikoff <[email protected]>
2026-07-16 20:19:57 -04:00

36 lines
939 B
TypeScript

import Link from 'next/link'
import { ReactNode } from 'react'
import { HydrationMarker } from './hydration-marker'
export default function Root({ children }: { children: ReactNode }) {
return (
<html>
<body
style={{
fontFamily:
'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif',
maxWidth: 900,
margin: '0 auto',
padding: '2rem 1rem',
lineHeight: 1.6,
color: '#111',
}}
>
<HydrationMarker />
<nav style={{ display: 'flex', gap: 12, marginBottom: '1rem' }}>
<Link href="/" id="link-to-home">
Home
</Link>
<Link href="/post/1" id="link-to-post-1">
Post 1
</Link>
<Link href="/post/2" id="link-to-post-2">
Post 2
</Link>
</nav>
{children}
</body>
</html>
)
}