-
-
Notifications
You must be signed in to change notification settings - Fork 426
Expand file tree
/
Copy pathmain.tsx
More file actions
85 lines (76 loc) · 2.25 KB
/
main.tsx
File metadata and controls
85 lines (76 loc) · 2.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import React from 'react'
import ReactDOM from 'react-dom/client'
import { useVirtualizer } from '@tanstack/react-virtual'
const COUNT = 500
// Rows mount at one height and then grow shortly after (simulates an image
// or async content loading and pushing the row taller). This is exactly the
// scenario where backward-scroll jumps happen: a row already in the measured
// cache at size X changes to size Y after a tiny delay, the ResizeObserver
// fires while the user is still scrolling up, and resizeItem triggers a
// scroll adjustment that visually jumps the page.
const Row: React.FC<{ index: number }> = ({ index }) => {
const [grown, setGrown] = React.useState(false)
React.useEffect(() => {
const t = setTimeout(() => setGrown(true), 150)
return () => clearTimeout(t)
}, [])
const extra = grown ? 60 + (index % 5) * 4 : 0
return (
<div
style={{
padding: 8,
height: 40 + extra,
boxSizing: 'border-box',
borderBottom: '1px solid #ccc',
}}
>
Row {index}
</div>
)
}
const App = () => {
const parentRef = React.useRef<HTMLDivElement>(null)
const rowVirtualizer = useVirtualizer({
count: COUNT,
getScrollElement: () => parentRef.current,
estimateSize: () => 50,
overscan: 5,
})
return (
<div>
<div
ref={parentRef}
id="scroll-container"
data-testid="scroll-container"
style={{ height: 400, width: 400, overflow: 'auto' }}
>
<div
style={{
height: rowVirtualizer.getTotalSize(),
position: 'relative',
width: '100%',
}}
>
{rowVirtualizer.getVirtualItems().map((v) => (
<div
key={v.key}
data-testid={`item-${v.index}`}
data-index={v.index}
ref={rowVirtualizer.measureElement}
style={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
transform: `translateY(${v.start}px)`,
}}
>
<Row index={v.index} />
</div>
))}
</div>
</div>
</div>
)
}
ReactDOM.createRoot(document.getElementById('root')!).render(<App />)