From 5e87a679dfe540c97a89565b0278333d360180a6 Mon Sep 17 00:00:00 2001 From: Arpita Patil Date: Sun, 4 Jan 2026 21:04:25 +0530 Subject: [PATCH] Optimize notification fetching and improve Load More UX --- client/src/modules/notification/index.tsx | 59 ++++++++++++++++++----- 1 file changed, 46 insertions(+), 13 deletions(-) diff --git a/client/src/modules/notification/index.tsx b/client/src/modules/notification/index.tsx index 26a3f266..7138ca74 100644 --- a/client/src/modules/notification/index.tsx +++ b/client/src/modules/notification/index.tsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from 'react'; +import { useEffect, useState,useRef,useCallback } from 'react'; import NotificationCard from './components/notificationCard'; import { notificationFilters } from './constants'; import { useSetAtom } from 'jotai'; @@ -23,38 +23,66 @@ import { import { NOTIFICATION_FILTER_TYPE } from '../../infra/rest/typings'; const Notifications = () => { + const prevFilterRef = useRef(null); const setNotifications = useSetAtom(NotificationsAtom); const [filter, setFilter] = useState( NOTIFICATION_FILTER_TYPE.ALL ); const { fetchNotifications, notifications } = useNotifications(); const { isAuthenticated } = useAuth(); + const [isLoadingMore, setIsLoadingMore] = useState(false); + const [isFilterLoading, setIsFilterLoading] = useState(false); + + // Avoid refetching notifications when the same filter is selected again useEffect(() => { - if (isAuthenticated()) { - setNotifications(null); - fetchNotifications({ page: 1, filter, deletedDocCount: 0 }); + if (!isAuthenticated()) return; + if (prevFilterRef.current === filter && notifications !== null) { + return; } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [filter]); + prevFilterRef.current = filter; + setIsFilterLoading(true); + setNotifications(null); + fetchNotifications({ + page: 1, + filter, + deletedDocCount: 0, + }).finally(() => { + setIsFilterLoading(false); +}); + + }, [filter, isAuthenticated, fetchNotifications, notifications, setNotifications]); - const handleFilter = (filterName: string) => { + + const handleFilter = useCallback((filterName: string) => { setFilter(filterName as NOTIFICATION_FILTER_TYPE); - }; + }, []); - const handleLoadMore = () => { + + const handleLoadMore = async () => { if ( - notifications && - notifications.results.length < notifications.totalDocs + !notifications || + isLoadingMore || + notifications.results.length >= notifications.totalDocs ) { - fetchNotifications({ + return; + } + + try { + setIsLoadingMore(true); + await fetchNotifications({ page: notifications.page + 1, filter, deletedDocCount: notifications.deleteDocCount || 0, }); + } + + finally { + setIsLoadingMore(false); } }; + return ( @@ -93,6 +121,7 @@ const Notifications = () => { variant={isActive ? 'contained' : 'outlined'} color={isActive ? 'primary' : 'inherit'} onClick={() => handleFilter(filterName)} + disabled={isFilterLoading} startIcon={ filterName === 'all' ? ( @@ -181,8 +210,12 @@ const Notifications = () => { onClick={handleLoadMore} variant="outlined" size="medium" + disabled={isLoadingMore} + startIcon={ + isLoadingMore ? : null + } > - Load More + {isLoadingMore ? 'Loading...' : 'Load More'} )}