Просмотр исходного кода

feat: Infinite scroll with SWRInfinite

https://youtrack.weseek.co.jp/issue/GW-7757
- Update getKey function
- Update fetcher function
- Update function to detect page loading is ending
- Update isReachingEnd type to boolean
I Komang Mudana 4 лет назад
Родитель
Сommit
67830c1ee4

+ 5 - 5
packages/app/src/components/Sidebar/InfiniteScroll.tsx

@@ -6,7 +6,7 @@ type Props<T> = {
   children: React.ReactChild | ((item: T) => React.ReactNode)
   loadingIndicator?: React.ReactNode
   endingIndicator?: React.ReactNode
-  isReachingEnd: boolean | ((swr: SWRInfiniteResponse<T>) => boolean)
+  isReachingEnd?: boolean,
   offset?: number
 }
 
@@ -37,20 +37,20 @@ const InfiniteScroll = <T, >(props: Props<T>): React.ReactElement<Props<T>> => {
 
   const [intersecting, ref] = useIntersection<HTMLDivElement>();
 
-  const ending = typeof isReachingEnd === 'function' ? isReachingEnd(swr) : isReachingEnd;
+  // const ending = typeof isReachingEnd === 'function' ? isReachingEnd(swr) : isReachingEnd;
 
   useEffect(() => {
-    if (intersecting && !isValidating && !ending) {
+    if (intersecting && !isValidating && !isReachingEnd) {
       setSize(size => size + 1);
     }
-  }, [intersecting, isValidating, setSize, ending]);
+  }, [intersecting, isValidating, setSize, isReachingEnd]);
 
   return (
     <>
       {typeof children === 'function' ? data?.map(item => children(item)) : children}
       <div style={{ position: 'relative' }}>
         <div ref={ref} style={{ position: 'absolute', top: offset }}></div>
-        {ending ? endingIndicator : loadingIndicator}
+        {isReachingEnd ? endingIndicator : loadingIndicator}
       </div>
     </>
   );

+ 10 - 4
packages/app/src/components/Sidebar/RecentChanges.tsx

@@ -127,7 +127,14 @@ const RecentChanges = (): JSX.Element => {
   const { t } = useTranslation();
   const swr = useSWRInifinitexRecentlyUpdated();
   const [isRecentChangesSidebarSmall, setIsRecentChangesSidebarSmall] = useState(false);
-
+  const ending = swr.data && swr.data[swr.data.length - 1]?.length < 20;
+  const pagiateResponse = (response) => {
+    console.log(response?.flat());
+    return Array.from(new Set(response?.flat().map(page => page._id)))
+      .map((id) => {
+        return response?.find(page => page._id === id);
+      });
+  };
   const retrieveSizePreferenceFromLocalStorage = useCallback(() => {
     if (window.localStorage.isRecentChangesSidebarSmall === 'true') {
       setIsRecentChangesSidebarSmall(true);
@@ -183,10 +190,9 @@ const RecentChanges = (): JSX.Element => {
           <InfiniteScroll
             swr={swr}
             // TODO detect reaching ends
-            isReachingEnd={swr => swr.data?.[0]?.items.length === 0 || 20 * swr.size > 177
-            }
+            isReachingEnd={ending}
           >
-            {response => response?.items.map(page => (
+            {response => pagiateResponse(response).map(page => (
               isRecentChangesSidebarSmall
                 ? <SmallPageItem key={page._id} page={page} />
                 : <LargePageItem key={page._id} page={page} />

+ 3 - 9
packages/app/src/stores/page.tsx

@@ -34,16 +34,10 @@ export const useSWRxRecentlyUpdated = (): SWRResponse<(IPageHasId)[], Error> =>
     endpoint => apiv3Get<{ pages:(IPageHasId)[] }>(endpoint).then(response => response.data?.pages),
   );
 };
-export const useSWRInifinitexRecentlyUpdated = () : SWRInfiniteResponse<IPagingResult<IPageHasId>, Error> => {
+export const useSWRInifinitexRecentlyUpdated = () : SWRInfiniteResponse<(IPageHasId)[], Error> => {
   return useSWRInfinite(
-    (offset: number) => `/pages/recent?offset=${offset}`,
-    (endpoint: string) => apiv3Get<{ pages:IPageHasId[], totalCount: number, limit: number }>(endpoint).then((response) => {
-      return {
-        items: response.data.pages,
-        totalCount: response.data.totalCount,
-        limit: response.data.limit,
-      };
-    }),
+    (offset: number) => `/pages/recent?offset=${offset + 1}`,
+    (endpoint: string) => apiv3Get<{ pages:(IPageHasId)[] }>(endpoint).then(response => response.data?.pages),
     {
       initialSize: 1,
       revalidateFirstPage: false,