feat: add scroll-to-top button and improve pagination handling
- Implemented a scroll-to-top button in the viewer UI for better navigation. - Added styles for the scroll-to-top button in viewer.html and viewer-template.html. - Created a new ScrollToTop component to manage visibility and scrolling behavior. - Updated Feed component to include the ScrollToTop component. - Enhanced pagination logic in usePagination hook to prevent stale closures and improve performance. - Modified SDKAgent to include additional observation fields for better data handling.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
import { useState, useEffect, useCallback, useRef } from 'react';
|
||||
import { Observation, Summary, UserPrompt } from '../types';
|
||||
import { UI } from '../constants/ui';
|
||||
import { API_ENDPOINTS } from '../constants/api';
|
||||
@@ -21,6 +21,18 @@ function usePaginationFor(endpoint: string, dataType: DataType, currentFilter: s
|
||||
});
|
||||
const [offset, setOffset] = useState(0);
|
||||
|
||||
// Use refs to avoid stale closures and prevent infinite loops
|
||||
const stateRef = useRef(state);
|
||||
const offsetRef = useRef(offset);
|
||||
|
||||
useEffect(() => {
|
||||
stateRef.current = state;
|
||||
}, [state]);
|
||||
|
||||
useEffect(() => {
|
||||
offsetRef.current = offset;
|
||||
}, [offset]);
|
||||
|
||||
// Reset pagination when filter changes
|
||||
useEffect(() => {
|
||||
setOffset(0);
|
||||
@@ -34,17 +46,17 @@ function usePaginationFor(endpoint: string, dataType: DataType, currentFilter: s
|
||||
* Load more items from the API
|
||||
*/
|
||||
const loadMore = useCallback(async (): Promise<DataItem[]> => {
|
||||
// Prevent concurrent requests using state
|
||||
if (state.isLoading || !state.hasMore) {
|
||||
// Prevent concurrent requests using ref (always current)
|
||||
if (stateRef.current.isLoading || !stateRef.current.hasMore) {
|
||||
return [];
|
||||
}
|
||||
|
||||
setState(prev => ({ ...prev, isLoading: true }));
|
||||
|
||||
try {
|
||||
// Build query params
|
||||
// Build query params using ref (always current)
|
||||
const params = new URLSearchParams({
|
||||
offset: offset.toString(),
|
||||
offset: offsetRef.current.toString(),
|
||||
limit: UI.PAGINATION_PAGE_SIZE.toString()
|
||||
});
|
||||
|
||||
@@ -74,7 +86,7 @@ function usePaginationFor(endpoint: string, dataType: DataType, currentFilter: s
|
||||
setState(prev => ({ ...prev, isLoading: false }));
|
||||
return [];
|
||||
}
|
||||
}, [offset, state.hasMore, state.isLoading, currentFilter, endpoint, dataType]);
|
||||
}, [currentFilter, endpoint, dataType]); // Only stable values - no state/offset deps
|
||||
|
||||
return {
|
||||
...state,
|
||||
|
||||
Reference in New Issue
Block a user