From 12767d907ee4b0be1c0b1f32223df1a14b18d003 Mon Sep 17 00:00:00 2001 From: Navin Karkera Date: Fri, 6 Sep 2024 13:07:33 +0530 Subject: [PATCH] refactor: move load on scroll logic to custom hook --- src/library-authoring/LibraryCollections.tsx | 29 +++++------------ .../components/LibraryComponents.tsx | 30 +++++------------- src/search-manager/SearchManager.ts | 31 +++++++++++++++++++ src/search-manager/index.ts | 2 +- 4 files changed, 47 insertions(+), 45 deletions(-) diff --git a/src/library-authoring/LibraryCollections.tsx b/src/library-authoring/LibraryCollections.tsx index f35214ffec..e037277066 100644 --- a/src/library-authoring/LibraryCollections.tsx +++ b/src/library-authoring/LibraryCollections.tsx @@ -1,7 +1,6 @@ -import React, { useEffect } from 'react'; import { CardGrid } from '@openedx/paragon'; -import { useSearchContext } from '../search-manager'; +import { useLoadOnScroll, useSearchContext } from '../search-manager'; import { NoComponents, NoSearchResults } from './EmptyStates'; import CollectionCard from './components/CollectionCard'; import { LIBRARY_SECTION_PREVIEW_LIMIT } from './components/LibrarySection'; @@ -29,26 +28,12 @@ const LibraryCollections = ({ variant }: LibraryCollectionsProps) => { const collectionList = variant === 'preview' ? collectionHits.slice(0, LIBRARY_SECTION_PREVIEW_LIMIT) : collectionHits; - useEffect(() => { - if (variant === 'full') { - const onscroll = () => { - // Verify the position of the scroll to implementa a infinite scroll. - // Used `loadLimit` to fetch next page before reach the end of the screen. - const loadLimit = 300; - const scrolledTo = window.scrollY + window.innerHeight; - const scrollDiff = document.body.scrollHeight - scrolledTo; - const isNearToBottom = scrollDiff <= loadLimit; - if (isNearToBottom && hasNextPage && !isFetchingNextPage) { - fetchNextPage(); - } - }; - window.addEventListener('scroll', onscroll); - return () => { - window.removeEventListener('scroll', onscroll); - }; - } - return () => {}; - }, [hasNextPage, isFetchingNextPage, fetchNextPage]); + useLoadOnScroll( + hasNextPage, + isFetchingNextPage, + fetchNextPage, + variant === 'full', + ); if (totalCollectionHits === 0) { return isFiltered ? : ; diff --git a/src/library-authoring/components/LibraryComponents.tsx b/src/library-authoring/components/LibraryComponents.tsx index 4065826428..2aa3014b7e 100644 --- a/src/library-authoring/components/LibraryComponents.tsx +++ b/src/library-authoring/components/LibraryComponents.tsx @@ -1,7 +1,7 @@ -import React, { useEffect, useMemo } from 'react'; +import React, { useMemo } from 'react'; import { CardGrid } from '@openedx/paragon'; -import { useSearchContext } from '../../search-manager'; +import { useLoadOnScroll, useSearchContext } from '../../search-manager'; import { NoComponents, NoSearchResults } from '../EmptyStates'; import { useLibraryBlockTypes } from '../data/apiHooks'; import ComponentCard from './ComponentCard'; @@ -43,26 +43,12 @@ const LibraryComponents = ({ libraryId, variant }: LibraryComponentsProps) => { return result; }, [blockTypesData]); - useEffect(() => { - if (variant === 'full') { - const onscroll = () => { - // Verify the position of the scroll to implementa a infinite scroll. - // Used `loadLimit` to fetch next page before reach the end of the screen. - const loadLimit = 300; - const scrolledTo = window.scrollY + window.innerHeight; - const scrollDiff = document.body.scrollHeight - scrolledTo; - const isNearToBottom = scrollDiff <= loadLimit; - if (isNearToBottom && hasNextPage && !isFetchingNextPage) { - fetchNextPage(); - } - }; - window.addEventListener('scroll', onscroll); - return () => { - window.removeEventListener('scroll', onscroll); - }; - } - return () => {}; - }, [hasNextPage, isFetchingNextPage, fetchNextPage]); + useLoadOnScroll( + hasNextPage, + isFetchingNextPage, + fetchNextPage, + variant === 'full', + ); if (componentCount === 0) { return isFiltered ? : ; diff --git a/src/search-manager/SearchManager.ts b/src/search-manager/SearchManager.ts index eca2b4cfbe..d636dc947d 100644 --- a/src/search-manager/SearchManager.ts +++ b/src/search-manager/SearchManager.ts @@ -185,3 +185,34 @@ export const useSearchContext = () => { } return ctx; }; + +/** + * Hook which loads next page of items on scroll + */ +export const useLoadOnScroll = ( + hasNextPage: boolean | undefined, + isFetchingNextPage: boolean, + fetchNextPage: () => void, + enabled: boolean, +) => { + React.useEffect(() => { + if (enabled) { + const onscroll = () => { + // Verify the position of the scroll to implementa a infinite scroll. + // Used `loadLimit` to fetch next page before reach the end of the screen. + const loadLimit = 300; + const scrolledTo = window.scrollY + window.innerHeight; + const scrollDiff = document.body.scrollHeight - scrolledTo; + const isNearToBottom = scrollDiff <= loadLimit; + if (isNearToBottom && hasNextPage && !isFetchingNextPage) { + fetchNextPage(); + } + }; + window.addEventListener('scroll', onscroll); + return () => { + window.removeEventListener('scroll', onscroll); + }; + } + return () => {}; + }, [hasNextPage, isFetchingNextPage, fetchNextPage]); +}; diff --git a/src/search-manager/index.ts b/src/search-manager/index.ts index 878bb14902..b06f9e193c 100644 --- a/src/search-manager/index.ts +++ b/src/search-manager/index.ts @@ -1,4 +1,4 @@ -export { SearchContextProvider, useSearchContext } from './SearchManager'; +export { SearchContextProvider, useLoadOnScroll, useSearchContext } from './SearchManager'; export { default as ClearFiltersButton } from './ClearFiltersButton'; export { default as FilterByBlockType } from './FilterByBlockType'; export { default as FilterByTags } from './FilterByTags';