diff options
Diffstat (limited to 'frontend/src')
| -rw-r--r-- | frontend/src/components/FeedItems.test.tsx | 5 | ||||
| -rw-r--r-- | frontend/src/components/FeedItems.tsx | 21 |
2 files changed, 19 insertions, 7 deletions
diff --git a/frontend/src/components/FeedItems.test.tsx b/frontend/src/components/FeedItems.test.tsx index 89c591c..fc95948 100644 --- a/frontend/src/components/FeedItems.test.tsx +++ b/frontend/src/components/FeedItems.test.tsx @@ -265,8 +265,13 @@ describe('FeedItems Component', () => { }); fireEvent.keyDown(window, { key: 'j' }); // index 0 + await waitFor(() => expect(document.getElementById('item-0')).toHaveAttribute('data-selected', 'true')); + fireEvent.keyDown(window, { key: 'j' }); // index 1 + await waitFor(() => expect(document.getElementById('item-1')).toHaveAttribute('data-selected', 'true')); + fireEvent.keyDown(window, { key: 'j' }); // index 2 (last item) + await waitFor(() => expect(document.getElementById('item-2')).toHaveAttribute('data-selected', 'true')); await waitFor(() => { expect(screen.getByText('Item 0')).toBeInTheDocument(); diff --git a/frontend/src/components/FeedItems.tsx b/frontend/src/components/FeedItems.tsx index 2c3253b..ea5d8fd 100644 --- a/frontend/src/components/FeedItems.tsx +++ b/frontend/src/components/FeedItems.tsx @@ -19,6 +19,7 @@ export default function FeedItems() { const hasMoreRef = useRef(hasMore); const [error, setError] = useState(''); const [selectedIndex, setSelectedIndex] = useState(-1); + const selectedIndexRef = useRef(selectedIndex); // Sync refs useEffect(() => { @@ -33,6 +34,10 @@ export default function FeedItems() { hasMoreRef.current = hasMore; }, [hasMore]); + useEffect(() => { + selectedIndexRef.current = selectedIndex; + }, [selectedIndex]); + const fetchItems = useCallback((maxId?: string) => { if (maxId) { setLoadingMore(true); @@ -156,8 +161,9 @@ export default function FeedItems() { if (currentItems.length === 0) return; if (e.key === 'j') { - const nextIndex = Math.min(selectedIndex + 1, currentItems.length - 1); - if (nextIndex !== selectedIndex) { + const nextIndex = Math.min(selectedIndexRef.current + 1, currentItems.length - 1); + if (nextIndex !== selectedIndexRef.current) { + selectedIndexRef.current = nextIndex; setSelectedIndex(nextIndex); const item = currentItems[nextIndex]; if (!item.read) { @@ -174,21 +180,22 @@ export default function FeedItems() { fetchItems(String(currentItems[currentItems.length - 1]._id)); } } else if (e.key === 'k') { - const nextIndex = Math.max(selectedIndex - 1, 0); - if (nextIndex !== selectedIndex) { + const nextIndex = Math.max(selectedIndexRef.current - 1, 0); + if (nextIndex !== selectedIndexRef.current) { + selectedIndexRef.current = nextIndex; setSelectedIndex(nextIndex); scrollToItem(nextIndex); } } else if (e.key === 's') { - if (selectedIndex >= 0 && selectedIndex < currentItems.length) { - toggleStar(currentItems[selectedIndex]); + if (selectedIndexRef.current >= 0 && selectedIndexRef.current < currentItems.length) { + toggleStar(currentItems[selectedIndexRef.current]); } } }; window.addEventListener('keydown', handleKeyDown); return () => window.removeEventListener('keydown', handleKeyDown); - }, [markAsRead, scrollToItem, toggleStar, fetchItems, selectedIndex]); + }, [markAsRead, scrollToItem, toggleStar, fetchItems]); // Stable Observer |
