Skip to content

Instantly share code, notes, and snippets.

@ywwwtseng
Last active August 28, 2024 11:03
Show Gist options
  • Save ywwwtseng/1fae8e7512d6ae758662d1fbede0d062 to your computer and use it in GitHub Desktop.
Save ywwwtseng/1fae8e7512d6ae758662d1fbede0d062 to your computer and use it in GitHub Desktop.
import { useState, useMemo } from 'react'
class ArrayUtil {
static range(...T) {
let start, end;
if (T.length === 1) {
start = 0;
end = T[0];
} else {
start = T[0];
end = T[1];
}
return {
map: function(callback) {
const array = [];
for (let index = start; index < end; index++) {
array.push(callback(index));
}
return array;
},
}
}
}
function VirtualList({
width,
height,
itemHeight,
data,
renderItem,
}) {
const [scrolltop, setScrolltop] = useState(0);
const yStart = Math.floor(scrolltop / itemHeight);
const yEnd = yStart + Math.ceil(height / itemHeight) + 1;
const indices = useMemo(() => ArrayUtil.range(yStart, yEnd), [yStart, yEnd]);
const handleWheel = (event) => {
setScrolltop(Math.min(Math.max(scrolltop + event.deltaY, 0), data.length * itemHeight - height));
}
return (
<div
style={{
position: 'relative',
width: `${width}px`,
height: `${height}px`,
overflow: 'hidden',
}}
onWheel={handleWheel}
>
<div
style={{
position: 'absolute',
top: '0px',
width: `${width}px`,
height: `${height}px`,
}}
>
{indices.map((itemIndex) => (
data[itemIndex] && <div
key={itemIndex}
style={{
height: `${itemHeight}px`,
width: '100%',
position: 'absolute',
top: `${itemIndex * itemHeight - scrolltop}px`,
background: '#f00'
}}>
{renderItem(data[itemIndex])}
</div>
))}
</div>
</div>
)
}
export default VirtualList
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment