From 9017b73b83e5ce5193d273cac9634962356245fa Mon Sep 17 00:00:00 2001 From: Sarah Rudder Date: Wed, 26 Feb 2025 14:49:12 -0600 Subject: [PATCH] add sort and don't flash when updating query --- frontend/hooks/useFileStorage.js | 41 +++++++++++++++++++++--- frontend/pages/file-storage/FileList.jsx | 11 ++----- frontend/pages/file-storage/index.js | 35 +++++++++++--------- frontend/util/federalistApi.js | 12 +++++-- 4 files changed, 68 insertions(+), 31 deletions(-) diff --git a/frontend/hooks/useFileStorage.js b/frontend/hooks/useFileStorage.js index edb25f5e0..a96805dbd 100644 --- a/frontend/hooks/useFileStorage.js +++ b/frontend/hooks/useFileStorage.js @@ -1,22 +1,53 @@ import { useQuery } from '@tanstack/react-query'; +import { useRef, useEffect } from 'react'; import federalist from '@util/federalistApi'; -export default function useFileStorage(fileStorageId, path = '') { +export default function useFileStorage( + fileStorageId, + path = '', + sortKey = null, + sortOrder = null +) { + // Create a ref to store previous data. (Declare it first!) + const previousData = useRef(); + const fetchPublicFiles = async () => { - const response = await federalist.fetchPublicFiles(fileStorageId, path); + const response = await federalist.fetchPublicFiles( + fileStorageId, + path, + sortKey, + sortOrder + ); if (response.error) { throw new Error(response.error); } return response.data; }; - const { data = [], isLoading, error, refetch } = useQuery({ - queryKey: ['fileStorage', fileStorageId, path], + // Use placeholderData: previousData.current if available. + const { data, isLoading, isFetching, error, refetch } = useQuery({ + queryKey: ['fileStorage', fileStorageId, path, sortKey, sortOrder], queryFn: fetchPublicFiles, enabled: !!fileStorageId, + keepPreviousData: true, + staleTime: 2000, + placeholderData: previousData.current || undefined, onError: (err) => console.error('Error fetching public files:', err), }); + // Update previousData whenever new data is available. + useEffect(() => { + if (data !== undefined) { + previousData.current = data; + } + }, [data]); - return { data, isLoading, error, refetch }; + return { + data, + previousData: previousData.current, + isLoading, + isFetching, + error, + refetch + }; } diff --git a/frontend/pages/file-storage/FileList.jsx b/frontend/pages/file-storage/FileList.jsx index ee36f1a93..438d9e6ff 100644 --- a/frontend/pages/file-storage/FileList.jsx +++ b/frontend/pages/file-storage/FileList.jsx @@ -122,8 +122,8 @@ const FileList = ({ onViewDetails, currentSortKey, currentSortOrder, + children, }) => { - const EMPTY_STATE_MESSAGE = 'No files or folders found.'; const TABLE_CAPTION = ` Listing all contents for the current folder, sorted by ${currentSortKey} in ${ariaFormatSort(currentSortOrder)} order @@ -192,6 +192,7 @@ const FileList = ({ + {children} {data.map((item) => ( ))} - {data.length === 0 && ( - - - {EMPTY_STATE_MESSAGE} - - - )} ); @@ -255,6 +249,7 @@ FileList.propTypes = { onSort: PropTypes.func.isRequired, currentSortKey: PropTypes.string.isRequired, currentSortOrder: PropTypes.oneOf(['asc', 'desc']).isRequired, + children: PropTypes.node, }; FileListRow.propTypes = { diff --git a/frontend/pages/file-storage/index.js b/frontend/pages/file-storage/index.js index c411391f7..3c921334c 100644 --- a/frontend/pages/file-storage/index.js +++ b/frontend/pages/file-storage/index.js @@ -24,34 +24,29 @@ function FileStoragePage() { if (path !== "/") { path = path.replace(/\/+$/, "") + "/"; } + const DEFAULT_SORT_KEY = "updatedAt"; + const DEFAULT_SORT_ORDER = "desc"; + const REVERSE_SORT_ORDER = "asc"; + + const sortKey = searchParams.get('sortKey') || DEFAULT_SORT_KEY; + const sortOrder = searchParams.get('sortOrder') || DEFAULT_SORT_ORDER; const { data: fetchedPublicFiles, isLoading, error, // refetch (if we need to manually update) - } = useFileStorage(fileStorageServiceId, path); - + } = useFileStorage(fileStorageServiceId, path, sortKey, sortOrder); const detailsFile = searchParams.get('details'); const storageRoot = `${site.siteOrigin}/~assets` - - const fileDetails = fetchedPublicFiles?.find(file => file.name === detailsFile); - const mockPagination = { currentPage: parseInt(searchParams.get('page')) || 1, totalPages: 20, totalItems: 392, }; - const DEFAULT_SORT_KEY = "name"; - const DEFAULT_SORT_ORDER = "asc"; - const REVERSE_SORT_ORDER = "desc"; - - const sortKey = searchParams.get('sortKey') || DEFAULT_SORT_KEY; - const sortOrder = searchParams.get('sortOrder') || DEFAULT_SORT_ORDER; - const mockedSort = { ...mockPagination, sortKey, @@ -130,7 +125,8 @@ function FileStoragePage() { }); }; - if (isLoading) { + + if (isLoading && fetchedPublicFiles === undefined) { return ; } @@ -169,15 +165,22 @@ function FileStoragePage() { - + > + {!isLoading && fetchedPublicFiles?.length === 0 && ( + + + No files or folders found. + + + )} +