Skip to content

Commit 1b7a83e

Browse files
authored
Ensure page is rendered before scrolling to top (#2721)
* Ensure the page is rendered before scrolling to top * Update links.spec.ts * wip
1 parent f7787d5 commit 1b7a83e

File tree

8 files changed

+399
-23
lines changed

8 files changed

+399
-23
lines changed

packages/react/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,12 @@
5959
"esbuild": "^0.25.12",
6060
"esbuild-node-externals": "^1.20.1",
6161
"react": "^19.2.0",
62+
"react-dom": "^19.2.0",
6263
"typescript": "^5.9.3"
6364
},
6465
"peerDependencies": {
65-
"react": "^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
66+
"react": "^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
67+
"react-dom": "^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
6668
},
6769
"dependencies": {
6870
"@inertiajs/core": "workspace:*",

packages/react/src/App.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
router,
99
} from '@inertiajs/core'
1010
import { createElement, FunctionComponent, ReactNode, useEffect, useMemo, useState } from 'react'
11+
import { flushSync } from 'react-dom'
1112
import HeadContext from './HeadContext'
1213
import PageContext from './PageContext'
1314
import { LayoutFunction, ReactComponent, ReactPageHandlerArgs } from './types'
@@ -79,11 +80,13 @@ export default function App<SharedProps extends PageProps = PageProps>({
7980
return
8081
}
8182

82-
setCurrent((current) => ({
83-
component,
84-
page,
85-
key: preserveState ? current.key : Date.now(),
86-
}))
83+
flushSync(() =>
84+
setCurrent((current) => ({
85+
component,
86+
page,
87+
key: preserveState ? current.key : Date.now(),
88+
})),
89+
)
8790
}
8891

8992
router.on('navigate', () => headManager.forceUpdate())
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import { Link } from '@inertiajs/react'
2+
3+
let originalScrollTo: typeof window.scrollTo | null = null
4+
5+
export default ({ page }: { page: number }) => {
6+
// Patch scrollTo to log synchronously when it's called (not when the scroll event fires)
7+
if (!originalScrollTo) {
8+
originalScrollTo = window.scrollTo.bind(window)
9+
10+
window.scrollTo = ((xOrOptions: number | ScrollToOptions, y?: number) => {
11+
const firstArgIsNumber = typeof xOrOptions === 'number'
12+
const scrollY = firstArgIsNumber ? y : (xOrOptions?.top ?? 0)
13+
14+
console.log('ScrollY', scrollY)
15+
16+
return firstArgIsNumber ? originalScrollTo!(xOrOptions, y!) : originalScrollTo!(xOrOptions)
17+
}) as typeof window.scrollTo
18+
} else {
19+
console.log('Render')
20+
}
21+
22+
return (
23+
<>
24+
<h1 style={{ fontSize: '40px' }}>Article Header</h1>
25+
<h2 style={{ fontSize: '40px' }}>Page {page}</h2>
26+
<article style={{ fontSize: '20px', maxWidth: '500px' }}>
27+
<p>
28+
Sunt culpa sit sunt enim aliquip. Esse ea ea quis voluptate. Enim consectetur aliqua ex ex magna cupidatat id
29+
minim sit elit.
30+
</p>
31+
<Link
32+
href={`/scroll-after-render/${page + 1}`}
33+
style={{ display: 'block', marginTop: '20px' }}
34+
onBefore={() => window.scrollTo(0, 100)}
35+
>
36+
Go to page {page + 1}
37+
</Link>
38+
{Array(500).map(() => (
39+
<div>
40+
<p>
41+
Sunt culpa sit sunt enim aliquip. Esse ea ea quis voluptate. Enim consectetur aliqua ex ex magna cupidatat
42+
id minim sit elit. Amet pariatur occaecat pariatur duis eiusmod dolore magna. Et commodo cupidatat in
43+
commodo elit cupidatat minim qui id non enim ad. Culpa aliquip ad Lorem sit consectetur ullamco culpa duis
44+
nisi et fugiat mollit eiusmod. Laboris voluptate veniam consequat proident in nulla irure velit.
45+
</p>
46+
47+
<p>
48+
Sit sint laboris sunt eiusmod ipsum laborum eiusmod amet commodo exercitation in duis magna. Proident sunt
49+
minim in elit qui. Id pariatur commodo fugiat excepteur in deserunt Lorem ipsum occaecat est. Excepteur
50+
sit tempor ipsum ex officia veniam enim amet velit fugiat mollit cillum. Incididunt aliqua nulla id
51+
occaecat nulla. Non ea ad est occaecat deserunt officia qui commodo exercitation.
52+
</p>
53+
54+
<p>
55+
Voluptate laborum quis aliqua ullamco magna amet ullamco laborum qui cillum eu. Dolore dolore aliqua
56+
proident proident sunt ipsum in. Enim velit dolore labore dolor quis incididunt duis culpa Lorem. Eu
57+
adipisicing non elit fugiat voluptate labore ipsum dolore consectetur commodo. Et in et cillum duis
58+
consequat quis ex eu commodo. Eiusmod aliqua excepteur consectetur eiusmod aute et consectetur sit
59+
pariatur dolore qui officia pariatur.
60+
</p>
61+
62+
<p>
63+
Non sunt eu mollit qui reprehenderit. Aute culpa anim voluptate do in esse duis laborum ad dolore. Ullamco
64+
nisi in nostrud officia do. Duis pariatur officia id duis. Deserunt ad incididunt est sint consectetur
65+
reprehenderit mollit est Lorem ea pariatur anim dolor adipisicing. Nostrud irure magna nostrud laboris
66+
aute sunt veniam laboris veniam incididunt sit. Nulla proident ad aliqua fugiat culpa sunt est in dolor
67+
velit ad irure nulla.
68+
</p>
69+
70+
<p>
71+
Do aute laborum deserunt non laborum voluptate voluptate. Anim ut laborum magna sunt cupidatat irure.
72+
Cupidatat fugiat minim sint cillum laborum excepteur irure id est irure ad occaecat adipisicing enim.
73+
Deserunt nulla anim proident velit irure nostrud est est reprehenderit consequat pariatur qui. Fugiat
74+
Lorem sint eu laborum minim pariatur cillum mollit nulla consequat ullamco ex. Ex consectetur ad ut irure
75+
fugiat occaecat aliqua exercitation cillum ipsum anim dolore tempor.
76+
</p>
77+
78+
<p>
79+
Adipisicing consequat irure fugiat Lorem deserunt aliquip do cupidatat. Lorem labore elit ex qui nostrud
80+
qui cillum sunt adipisicing occaecat. Sunt nostrud amet amet cupidatat fugiat Lorem quis nulla id cillum
81+
esse eu. Ullamco aliqua dolore irure amet mollit anim velit dolore.
82+
</p>
83+
84+
<p>
85+
Veniam cupidatat ipsum ea officia ipsum nisi laborum culpa qui dolore. Aliqua Lorem nisi labore ea velit
86+
aliquip irure excepteur eu. Laboris proident duis non labore sunt quis aute tempor laboris enim anim
87+
eiusmod.
88+
</p>
89+
90+
<p>
91+
Minim proident ut aliqua ea ut culpa fugiat ullamco nisi esse nostrud reprehenderit id. Id id ullamco
92+
velit anim nisi magna Lorem tempor. Et veniam occaecat ut labore consequat fugiat duis.
93+
</p>
94+
95+
<p>
96+
Adipisicing ea consectetur adipisicing aute eu pariatur enim labore consequat occaecat consectetur minim
97+
nisi. Cillum commodo sunt labore reprehenderit. Duis esse excepteur magna tempor eiusmod exercitation
98+
Lorem reprehenderit excepteur pariatur. Esse cupidatat occaecat magna do aliquip Lorem. Consectetur
99+
adipisicing consequat dolore nostrud esse eu cillum id commodo duis. Aliquip dolor cillum cupidatat
100+
fugiat.
101+
</p>
102+
103+
<p>
104+
Ex eiusmod id est laborum sunt ex ea aute adipisicing ad magna deserunt duis. Nostrud velit dolore id
105+
commodo quis enim fugiat. Sint non quis consectetur voluptate aliqua dolore nulla. Irure sit reprehenderit
106+
sint laboris non elit. Duis minim nisi esse dolor. Sit ex in consequat non occaecat commodo irure et.
107+
Commodo qui ipsum Lorem magna consequat consequat et minim eiusmod Lorem eiusmod cupidatat voluptate.
108+
</p>
109+
</div>
110+
))}
111+
</article>
112+
</>
113+
)
114+
}
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
<script context="module" lang="ts">
2+
let originalScrollTo: typeof window.scrollTo | null = null
3+
</script>
4+
5+
<script lang="ts">
6+
import { Link } from '@inertiajs/svelte'
7+
8+
export let page: number
9+
10+
// Patch scrollTo to log synchronously when it's called (not when the scroll event fires)
11+
if (!originalScrollTo) {
12+
originalScrollTo = window.scrollTo.bind(window)
13+
14+
window.scrollTo = ((xOrOptions: number | ScrollToOptions, y?: number) => {
15+
const firstArgIsNumber = typeof xOrOptions === 'number'
16+
const scrollY = firstArgIsNumber ? y : (xOrOptions?.top ?? 0)
17+
18+
console.log('ScrollY', scrollY)
19+
20+
return firstArgIsNumber ? originalScrollTo!(xOrOptions, y!) : originalScrollTo!(xOrOptions)
21+
}) as typeof window.scrollTo
22+
} else {
23+
console.log('Render')
24+
}
25+
26+
function beforeNavigate() {
27+
window.scrollTo(0, 100)
28+
}
29+
</script>
30+
31+
<h1 style="font-size: 40px;">Article Header</h1>
32+
<h2 style="font-size: 40px;">Page {page}</h2>
33+
<article style="font-size: 20px; max-width: 500px;">
34+
<p>
35+
Sunt culpa sit sunt enim aliquip. Esse ea ea quis voluptate. Enim consectetur aliqua ex ex magna cupidatat id minim
36+
sit elit.
37+
</p>
38+
<Link href={`/scroll-after-render/${page + 1}`} style="display: block; margin-top: 20px;" on:before={beforeNavigate}>
39+
Go to page {page + 1}
40+
</Link>
41+
{#each Array(500).keys() as i (i)}
42+
<div>
43+
<p>
44+
Sunt culpa sit sunt enim aliquip. Esse ea ea quis voluptate. Enim consectetur aliqua ex ex magna cupidatat id
45+
minim sit elit. Amet pariatur occaecat pariatur duis eiusmod dolore magna. Et commodo cupidatat in commodo elit
46+
cupidatat minim qui id non enim ad. Culpa aliquip ad Lorem sit consectetur ullamco culpa duis nisi et fugiat
47+
mollit eiusmod. Laboris voluptate veniam consequat proident in nulla irure velit.
48+
</p>
49+
50+
<p>
51+
Sit sint laboris sunt eiusmod ipsum laborum eiusmod amet commodo exercitation in duis magna. Proident sunt minim
52+
in elit qui. Id pariatur commodo fugiat excepteur in deserunt Lorem ipsum occaecat est. Excepteur sit tempor
53+
ipsum ex officia veniam enim amet velit fugiat mollit cillum. Incididunt aliqua nulla id occaecat nulla. Non ea
54+
ad est occaecat deserunt officia qui commodo exercitation.
55+
</p>
56+
57+
<p>
58+
Voluptate laborum quis aliqua ullamco magna amet ullamco laborum qui cillum eu. Dolore dolore aliqua proident
59+
proident sunt ipsum in. Enim velit dolore labore dolor quis incididunt duis culpa Lorem. Eu adipisicing non elit
60+
fugiat voluptate labore ipsum dolore consectetur commodo. Et in et cillum duis consequat quis ex eu commodo.
61+
Eiusmod aliqua excepteur consectetur eiusmod aute et consectetur sit pariatur dolore qui officia pariatur.
62+
</p>
63+
64+
<p>
65+
Non sunt eu mollit qui reprehenderit. Aute culpa anim voluptate do in esse duis laborum ad dolore. Ullamco nisi
66+
in nostrud officia do. Duis pariatur officia id duis. Deserunt ad incididunt est sint consectetur reprehenderit
67+
mollit est Lorem ea pariatur anim dolor adipisicing. Nostrud irure magna nostrud laboris aute sunt veniam
68+
laboris veniam incididunt sit. Nulla proident ad aliqua fugiat culpa sunt est in dolor velit ad irure nulla.
69+
</p>
70+
71+
<p>
72+
Do aute laborum deserunt non laborum voluptate voluptate. Anim ut laborum magna sunt cupidatat irure. Cupidatat
73+
fugiat minim sint cillum laborum excepteur irure id est irure ad occaecat adipisicing enim. Deserunt nulla anim
74+
proident velit irure nostrud est est reprehenderit consequat pariatur qui. Fugiat Lorem sint eu laborum minim
75+
pariatur cillum mollit nulla consequat ullamco ex. Ex consectetur ad ut irure fugiat occaecat aliqua
76+
exercitation cillum ipsum anim dolore tempor.
77+
</p>
78+
79+
<p>
80+
Adipisicing consequat irure fugiat Lorem deserunt aliquip do cupidatat. Lorem labore elit ex qui nostrud qui
81+
cillum sunt adipisicing occaecat. Sunt nostrud amet amet cupidatat fugiat Lorem quis nulla id cillum esse eu.
82+
Ullamco aliqua dolore irure amet mollit anim velit dolore.
83+
</p>
84+
85+
<p>
86+
Veniam cupidatat ipsum ea officia ipsum nisi laborum culpa qui dolore. Aliqua Lorem nisi labore ea velit aliquip
87+
irure excepteur eu. Laboris proident duis non labore sunt quis aute tempor laboris enim anim eiusmod.
88+
</p>
89+
90+
<p>
91+
Minim proident ut aliqua ea ut culpa fugiat ullamco nisi esse nostrud reprehenderit id. Id id ullamco velit anim
92+
nisi magna Lorem tempor. Et veniam occaecat ut labore consequat fugiat duis.
93+
</p>
94+
95+
<p>
96+
Adipisicing ea consectetur adipisicing aute eu pariatur enim labore consequat occaecat consectetur minim nisi.
97+
Cillum commodo sunt labore reprehenderit. Duis esse excepteur magna tempor eiusmod exercitation Lorem
98+
reprehenderit excepteur pariatur. Esse cupidatat occaecat magna do aliquip Lorem. Consectetur adipisicing
99+
consequat dolore nostrud esse eu cillum id commodo duis. Aliquip dolor cillum cupidatat fugiat.
100+
</p>
101+
102+
<p>
103+
Ex eiusmod id est laborum sunt ex ea aute adipisicing ad magna deserunt duis. Nostrud velit dolore id commodo
104+
quis enim fugiat. Sint non quis consectetur voluptate aliqua dolore nulla. Irure sit reprehenderit sint laboris
105+
non elit. Duis minim nisi esse dolor. Sit ex in consequat non occaecat commodo irure et. Commodo qui ipsum Lorem
106+
magna consequat consequat et minim eiusmod Lorem eiusmod cupidatat voluptate.
107+
</p>
108+
</div>
109+
{/each}
110+
</article>
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
<script lang="ts">
2+
let originalScrollTo: typeof window.scrollTo | null = null
3+
</script>
4+
5+
<script setup lang="ts">
6+
import { Link } from '@inertiajs/vue3'
7+
8+
defineProps<{
9+
page: number
10+
}>()
11+
12+
// Patch scrollTo to log synchronously when it's called (not when the scroll event fires)
13+
if (!originalScrollTo) {
14+
originalScrollTo = window.scrollTo.bind(window)
15+
16+
window.scrollTo = ((xOrOptions: number | ScrollToOptions, y?: number) => {
17+
const firstArgIsNumber = typeof xOrOptions === 'number'
18+
const scrollY = firstArgIsNumber ? y : (xOrOptions?.top ?? 0)
19+
20+
console.log('ScrollY', scrollY)
21+
22+
return firstArgIsNumber ? originalScrollTo!(xOrOptions, y!) : originalScrollTo!(xOrOptions)
23+
}) as typeof window.scrollTo
24+
} else {
25+
console.log('Render')
26+
}
27+
28+
function beforeNavigate() {
29+
window.scrollTo(0, 100)
30+
}
31+
</script>
32+
33+
<template>
34+
<h1 :style="{ fontSize: '40px' }">Article Header</h1>
35+
<h2 :style="{ fontSize: '40px' }">Page {{ page }}</h2>
36+
<article :style="{ fontSize: '20px', maxWidth: '500px' }">
37+
<p>
38+
Sunt culpa sit sunt enim aliquip. Esse ea ea quis voluptate. Enim consectetur aliqua ex ex magna cupidatat id
39+
minim sit elit.
40+
</p>
41+
<Link
42+
:href="`/scroll-after-render/${page + 1}`"
43+
:style="{ display: 'block', marginTop: '20px' }"
44+
@before="beforeNavigate"
45+
>
46+
Go to page {{ page + 1 }}
47+
</Link>
48+
<div v-for="i in [...Array(500).keys()]" :key="i">
49+
<p>
50+
Sunt culpa sit sunt enim aliquip. Esse ea ea quis voluptate. Enim consectetur aliqua ex ex magna cupidatat id
51+
minim sit elit. Amet pariatur occaecat pariatur duis eiusmod dolore magna. Et commodo cupidatat in commodo elit
52+
cupidatat minim qui id non enim ad. Culpa aliquip ad Lorem sit consectetur ullamco culpa duis nisi et fugiat
53+
mollit eiusmod. Laboris voluptate veniam consequat proident in nulla irure velit.
54+
</p>
55+
56+
<p>
57+
Sit sint laboris sunt eiusmod ipsum laborum eiusmod amet commodo exercitation in duis magna. Proident sunt minim
58+
in elit qui. Id pariatur commodo fugiat excepteur in deserunt Lorem ipsum occaecat est. Excepteur sit tempor
59+
ipsum ex officia veniam enim amet velit fugiat mollit cillum. Incididunt aliqua nulla id occaecat nulla. Non ea
60+
ad est occaecat deserunt officia qui commodo exercitation.
61+
</p>
62+
63+
<p>
64+
Voluptate laborum quis aliqua ullamco magna amet ullamco laborum qui cillum eu. Dolore dolore aliqua proident
65+
proident sunt ipsum in. Enim velit dolore labore dolor quis incididunt duis culpa Lorem. Eu adipisicing non elit
66+
fugiat voluptate labore ipsum dolore consectetur commodo. Et in et cillum duis consequat quis ex eu commodo.
67+
Eiusmod aliqua excepteur consectetur eiusmod aute et consectetur sit pariatur dolore qui officia pariatur.
68+
</p>
69+
70+
<p>
71+
Non sunt eu mollit qui reprehenderit. Aute culpa anim voluptate do in esse duis laborum ad dolore. Ullamco nisi
72+
in nostrud officia do. Duis pariatur officia id duis. Deserunt ad incididunt est sint consectetur reprehenderit
73+
mollit est Lorem ea pariatur anim dolor adipisicing. Nostrud irure magna nostrud laboris aute sunt veniam
74+
laboris veniam incididunt sit. Nulla proident ad aliqua fugiat culpa sunt est in dolor velit ad irure nulla.
75+
</p>
76+
77+
<p>
78+
Do aute laborum deserunt non laborum voluptate voluptate. Anim ut laborum magna sunt cupidatat irure. Cupidatat
79+
fugiat minim sint cillum laborum excepteur irure id est irure ad occaecat adipisicing enim. Deserunt nulla anim
80+
proident velit irure nostrud est est reprehenderit consequat pariatur qui. Fugiat Lorem sint eu laborum minim
81+
pariatur cillum mollit nulla consequat ullamco ex. Ex consectetur ad ut irure fugiat occaecat aliqua
82+
exercitation cillum ipsum anim dolore tempor.
83+
</p>
84+
85+
<p>
86+
Adipisicing consequat irure fugiat Lorem deserunt aliquip do cupidatat. Lorem labore elit ex qui nostrud qui
87+
cillum sunt adipisicing occaecat. Sunt nostrud amet amet cupidatat fugiat Lorem quis nulla id cillum esse eu.
88+
Ullamco aliqua dolore irure amet mollit anim velit dolore.
89+
</p>
90+
91+
<p>
92+
Veniam cupidatat ipsum ea officia ipsum nisi laborum culpa qui dolore. Aliqua Lorem nisi labore ea velit aliquip
93+
irure excepteur eu. Laboris proident duis non labore sunt quis aute tempor laboris enim anim eiusmod.
94+
</p>
95+
96+
<p>
97+
Minim proident ut aliqua ea ut culpa fugiat ullamco nisi esse nostrud reprehenderit id. Id id ullamco velit anim
98+
nisi magna Lorem tempor. Et veniam occaecat ut labore consequat fugiat duis.
99+
</p>
100+
101+
<p>
102+
Adipisicing ea consectetur adipisicing aute eu pariatur enim labore consequat occaecat consectetur minim nisi.
103+
Cillum commodo sunt labore reprehenderit. Duis esse excepteur magna tempor eiusmod exercitation Lorem
104+
reprehenderit excepteur pariatur. Esse cupidatat occaecat magna do aliquip Lorem. Consectetur adipisicing
105+
consequat dolore nostrud esse eu cillum id commodo duis. Aliquip dolor cillum cupidatat fugiat.
106+
</p>
107+
108+
<p>
109+
Ex eiusmod id est laborum sunt ex ea aute adipisicing ad magna deserunt duis. Nostrud velit dolore id commodo
110+
quis enim fugiat. Sint non quis consectetur voluptate aliqua dolore nulla. Irure sit reprehenderit sint laboris
111+
non elit. Duis minim nisi esse dolor. Sit ex in consequat non occaecat commodo irure et. Commodo qui ipsum Lorem
112+
magna consequat consequat et minim eiusmod Lorem eiusmod cupidatat voluptate.
113+
</p>
114+
</div>
115+
</article>
116+
</template>

pnpm-lock.yaml

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)