Back to questions
Middle
2
Как реализовать клавиатурную навигацию (стрелки вверх/вниз) в виртуализированном списке с использованием @tanstack/virtual?
Companies where asked
Ifellow
Answer from AI
sobes.tech AI
Для реализации клавиатурной навигации (стрелки вверх/вниз) в виртуализированном списке с использованием @tanstack/virtual нужно управлять текущим выделенным индексом и прокручивать список к нужному элементу при изменении этого индекса.
Основные шаги:
- Хранить в состоянии индекс текущего выделенного элемента.
- Обрабатывать события клавиатуры (keydown) на контейнере списка.
- При нажатии стрелки вниз увеличивать индекс, при стрелке вверх — уменьшать, с проверкой границ.
- Использовать метод
scrollToIndexиз API @tanstack/virtual, чтобы прокрутить список к выделенному элементу.
Пример на React:
import React, { useState, useRef, useEffect } from 'react';
import { useVirtual } from '@tanstack/react-virtual';
function VirtualList({ items }) {
const parentRef = useRef(null);
const [highlightedIndex, setHighlightedIndex] = useState(0);
const rowVirtualizer = useVirtual({
size: items.length,
parentRef,
estimateSize: () => 35,
overscan: 5,
});
useEffect(() => {
rowVirtualizer.scrollToIndex(highlightedIndex);
}, [highlightedIndex, rowVirtualizer]);
const onKeyDown = (e) => {
if (e.key === 'ArrowDown') {
e.preventDefault();
setHighlightedIndex(i => Math.min(i + 1, items.length - 1));
} else if (e.key === 'ArrowUp') {
e.preventDefault();
setHighlightedIndex(i => Math.max(i - 1, 0));
}
};
return (
<div
ref={parentRef}
tabIndex={0}
onKeyDown={onKeyDown}
style={{ height: `300px`, overflow: 'auto', outline: 'none' }}
>
<div
style={{
height: `${rowVirtualizer.totalSize}px`,
position: 'relative',
}}
>
{rowVirtualizer.virtualItems.map(virtualRow => {
const isSelected = virtualRow.index === highlightedIndex;
return (
<div
key={virtualRow.index}
ref={virtualRow.measureRef}
style={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: `${virtualRow.size}px`,
transform: `translateY(${virtualRow.start}px)`,
backgroundColor: isSelected ? '#bde4ff' : 'transparent',
padding: '8px',
boxSizing: 'border-box',
}}
>
{items[virtualRow.index]}
</div>
);
})}
</div>
</div>
);
}
В этом примере при нажатии стрелок меняется выделенный индекс, и список прокручивается к нему, обеспечивая удобную клавиатурную навигацию.