Skip to content

Commit 88898df

Browse files
Merge pull request #342 from preactjs/virtual-scroll
2 parents ba9d0fa + 60b2a73 commit 88898df

File tree

3 files changed

+49
-5
lines changed

3 files changed

+49
-5
lines changed

src/view/components/elements/VirtualizedList.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,28 +34,30 @@ export function useVirtualizedList<T>({
3434
const timeoutRef = useRef<any>(null);
3535
const scrollToItem = useCallback(
3636
(item: T) => {
37+
if (timeoutRef.current) {
38+
clearTimeout(timeoutRef.current);
39+
}
40+
3741
const nextIdx = items.findIndex(t => t === item);
3842
if (nextIdx < 0) return;
3943

44+
// Check if the item we want to scroll to is already in view
4045
const pos = Math.floor(nextIdx * rowHeight);
41-
if (top > pos || max < pos) {
46+
if (scroll > pos || scroll + height < pos) {
4247
// Clamp to available range to avoid overflow
4348
const maxScroll = Math.floor(rowHeight * items.length - height);
4449
const nextPos = Math.max(0, Math.min(pos, maxScroll));
4550

4651
// Debounce scroll to avoid flickering when quickly hovering
4752
// a bunch of elements
48-
if (timeoutRef.current) {
49-
clearTimeout(timeoutRef.current);
50-
}
5153
timeoutRef.current = setTimeout(() => {
5254
if (container.current) {
5355
container.current.scrollTop = nextPos;
5456
}
5557
}, 100);
5658
}
5759
},
58-
[items],
60+
[items, scroll, rowHeight, height],
5961
);
6062

6163
useLayoutEffect(() => {

test-e2e/fixtures/apps/deep-tree-2.jsx

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,31 @@ function Foo() {
1919
);
2020
}
2121

22+
function Bar() {
23+
return (
24+
<h1 id="bar" data-testid="bar">
25+
BAR
26+
</h1>
27+
);
28+
}
29+
30+
function Bar2() {
31+
return (
32+
<h1 id="bar2" data-testid="bar2">
33+
BAR 2
34+
</h1>
35+
);
36+
}
37+
2238
function App() {
2339
return (
2440
<Fragment>
2541
<ChildItemName>
42+
<Bar />
2643
<ChildItemName>
2744
<ChildItemName>
2845
<ChildItemName>
46+
<Bar2 />
2947
<ChildItemName>
3048
<ChildItemName>
3149
<ChildItemName>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { newTestPage, installMouseHelper, clickTreeItem } from "../test-utils";
2+
import { expect } from "chai";
3+
import { wait } from "pentf/utils";
4+
5+
export const description =
6+
"Don't scroll a virtualized element if already visible";
7+
8+
export async function run(config: any) {
9+
const { devtools } = await newTestPage(config, "deep-tree-2");
10+
await installMouseHelper(devtools);
11+
12+
const selector = '[data-name="App"]';
13+
await devtools.waitForSelector(selector);
14+
15+
await clickTreeItem(devtools, "Bar");
16+
17+
await wait(2000);
18+
19+
const scroll = await devtools.evaluate(() => {
20+
return Number(document.querySelector('[data-tree="true"]')?.scrollTop);
21+
});
22+
23+
expect(scroll).to.equal(0);
24+
}

0 commit comments

Comments
 (0)