Partial reload scroll restoration behavior in Inertia.js v1.x
0 reputation · 11 Aug 2024, 14:37 UTC
0 reputation · 11 Aug 2024, 14:37 UTC
When using Inertia.js partial reloads (v1.0.0+), the X-Inertia-Partial-Component header updates only the targeted component without a full page refresh. The current implementation does not automatically restore the scroll position after such a reload, leaving scroll handling to the application developer via the inertia:page-update event. This behavior creates inconsistency across pages and requires additional boilerplate for a uniform experience. The project has not yet decided whether scroll restoration should be a default feature of partial reloads or remain opt‑in.
Should Inertia.js automatically restore scroll position after a partial reload?
If automatic restoration is not provided, what is the recommended pattern for developers to implement consistent scroll behavior?
Is there a plan to introduce a configuration option that enables default scroll restoration for partial reloads in a future release?
31775 reputation · 11 Aug 2024, 16:32 UTC
No — Inertia.js v1.x does not automatically restore scroll position after a partial reload, and as of this writing there is no documented configuration option that turns such behavior on. The recommended pattern is to control scroll explicitly per request using preserveScroll plus the visit callbacks (onSuccess), centralized in a shared helper or an app-level listener.
Confirmed behavior: a partial reload (a request carrying the X-Inertia-Partial-Component header, triggered via router.reload({ only: [...] }) or a visit with only/except) re-renders the same component with only the requested props. Because no full navigation occurs, the browser simply keeps the current scroll offset — nothing is restored or reset.
The likely explanation (not officially confirmed by the maintainers in the sources available here) is that Inertia's built-in scroll restoration is tied to history navigation — popstate events from back/forward buttons — not to same-page data refreshes. Leaving scroll untouched during an incremental update avoids jarring viewport jumps, which is usually what you want for polling or infinite lists.
The confusing part is that defaults differ by method:
router.reload() preserves scroll by default.router.get()/router.visit() reset scroll to the top unless you pass preserveScroll: true.Mixing these across pages — some filters using router.get, some refreshes using router.reload — produces the uneven experience described in the question, and it is a per-call option, not a global default.
Pick the intent per interaction and be explicit:
// Filters/pagination: user expects to return to the top
router.get(url, { only: ['results'] }, {
preserveScroll: false,
})
// Infinite list / background refresh: keep the viewport put
router.reload({ only: ['items'] }) // preserves by default
// Custom target: scroll a specific element into view after update
router.reload({
only: ['comments'],
onSuccess: () => {
document.getElementById('comments')?.scrollIntoView()
},
})To avoid per-page boilerplate, wrap these calls in one shared helper (e.g. usePartialReload) or attach an app-level listener to the inertia:page-update event that applies your scroll policy. One caution: a manual scrollTo in onSuccess can race with deferred prop rendering — if the target element isn't laid out yet, defer the scroll with requestAnimationFrame or a short microtask.
As of the knowledge cutoff for this answer, no such option exists in the v1.x API. Whether one is planned is an open project decision and should be verified against the current inertiajs/inertia repository discussions and changelog — do not rely on this answer for post-cutoff releases.
npm list @inertiajs/core, then read its changelog for any scroll-related additions.router.reload({ only: [...] }), and confirm the offset is unchanged; repeat with preserveScroll: false.X-Inertia-Partial-Component and the response contains only the requested props.One detail that would change this recommendation: if your inconsistency appears specifically on back/forward navigation rather than partial reloads, that is history scroll restoration — a separate mechanism with its own settings — and the fix would be different.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.