Skip to content

Commit 77418dd

Browse files
committed
Possible solution to scroll-jump
1 parent be1700c commit 77418dd

File tree

4 files changed

+28
-13
lines changed

4 files changed

+28
-13
lines changed

lib/components/list/useDynamicRowHeight.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,4 +197,6 @@ describe("useDynamicRowHeight", () => {
197197
});
198198

199199
// setRowHeight is tested indirectly by "getAverageRowHeight" and "getRowHeight" blocks above
200+
201+
// TODO Add tests for issue #863
200202
});

lib/components/list/useDynamicRowHeight.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,24 @@ export function useDynamicRowHeight({
3939
return defaultRowHeight;
4040
}
4141

42-
return totalHeight / map.size;
42+
return Math.round(totalHeight / map.size);
4343
}, [defaultRowHeight, map]);
4444

4545
const getRowHeight = useCallback(
4646
(index: number) => {
47-
return map.get(index);
47+
const measuredHeight = map.get(index);
48+
if (measuredHeight !== undefined) {
49+
return measuredHeight;
50+
}
51+
52+
// Temporarily store default height in the cache map to avoid scroll jumps if rowProps change
53+
// Else rowProps changes can impact the average height, and cause rows to shift up or down within the list
54+
// see github.com/bvaughn/react-window/issues/863
55+
map.set(index, defaultRowHeight);
56+
57+
return defaultRowHeight;
4858
},
49-
[map]
59+
[defaultRowHeight, map]
5060
);
5161

5262
const setRowHeight = useCallback((index: number, size: number) => {

lib/hooks/useStableCallback.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export function useStableCallback<Args, Return>(
66
fn: (args: Args) => Return
77
): (args: Args) => Return {
88
const ref = useRef<typeof fn>(() => {
9-
throw new Error("Cannot call an event handler while rendering.");
9+
throw new Error("Cannot call during render.");
1010
});
1111

1212
useIsomorphicLayoutEffect(() => {

src/routes/ScratchpadRoute.tsx

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
type Item = {
1010
children: Array<{ index: number }>;
1111
id: number;
12+
minHeight: number;
1213
name: string;
1314
};
1415

@@ -86,20 +87,21 @@ function Row({
8687
items: Item[];
8788
toggleExpand: (id: number) => void;
8889
}>) {
89-
const item = items[index];
90+
const { children, minHeight, name } = items[index];
91+
9092
const isExpanded = expandedSet.has(index);
9193

9294
return (
93-
<div className="py-1 px-2 flex items-center gap-2" style={style}>
94-
<Button
95-
disabled={!item.children.length}
96-
onClick={() => toggleExpand(index)}
97-
>
98-
{!item.children.length || isExpanded ? "–" : "+"}
95+
<div
96+
className="py-1 px-2 flex items-center gap-2"
97+
style={{ ...style, minHeight }}
98+
>
99+
<Button disabled={!children.length} onClick={() => toggleExpand(index)}>
100+
{!children.length || isExpanded ? "–" : "+"}
99101
</Button>
100-
{item.name}
102+
{name}
101103
{isExpanded && (
102-
<pre className="text-xs">{JSON.stringify(item.children, null, 2)}</pre>
104+
<pre className="text-xs">{JSON.stringify(children, null, 2)}</pre>
103105
)}
104106
</div>
105107
);
@@ -114,6 +116,7 @@ function createItems() {
114116
index
115117
})),
116118
id: index,
119+
minHeight: 24 + 5 * (index % 3),
117120
name: `item ${index}`
118121
});
119122
}

0 commit comments

Comments
 (0)