diff --git a/packages/react-pdf/src/components/Pages.tsx b/packages/react-pdf/src/components/Pages.tsx index a992895..1cebebe 100644 --- a/packages/react-pdf/src/components/Pages.tsx +++ b/packages/react-pdf/src/components/Pages.tsx @@ -1,6 +1,7 @@ -import {PropsWithChildren, memo, useState} from 'react' +import {PropsWithChildren, memo, useCallback, useState} from 'react' import {usePdfContext} from '../contexts/pdf' +import useInfiniteScroll from '../hooks/useInfiniteScroll' import {useIsomorphicLayoutEffect} from '../hooks/useIsomorphicLayoutEffect' import {PDFPageProxy} from '../pdfjs-dist/types/pdfjs' import {AnnotationLayer} from './layer/Annotation' @@ -10,6 +11,7 @@ import {PageSvg} from './page/Svg' export interface PagesProps { renderMode?: 'canvas' | 'svg' + lazyLoading?: boolean } export const Page = memo(function Page({renderMode, pageNumber}: PagesProps & {pageNumber: number}) { @@ -38,15 +40,30 @@ export const Page = memo(function Page({renderMode, pageNumber}: PagesProps & {p ) }) -export const Pages = memo(function Pages({renderMode, children}: PropsWithChildren) { +export const Pages = memo(function Pages({renderMode, lazyLoading, children}: PropsWithChildren) { const {pdf} = usePdfContext() + const pageNumbers = Array.from({length: pdf.numPages}, (_, index) => index + 1) + const [renderPages, setRenderPages] = useState(pdf.numPages > 0 ? [1] : []) - // TODO : 무한 스크롤 + const handleIntersect = useCallback(() => { + setRenderPages((prev) => { + if (prev.length < pageNumbers.length) { + return [...prev, prev.length + 1] + } + return prev + }) + }, [pageNumbers]) + + const ref = useInfiniteScroll(handleIntersect, {threshold: 0.5}) return ( <> - {Array.from({length: pdf.numPages}).map((_, index) => { - return + {(lazyLoading ? renderPages : pageNumbers).map((pageNum) => { + return ( +
+ +
+ ) })} {children} diff --git a/packages/react-pdf/src/components/PdfViewer.tsx b/packages/react-pdf/src/components/PdfViewer.tsx index 1fced97..6484bd2 100644 --- a/packages/react-pdf/src/components/PdfViewer.tsx +++ b/packages/react-pdf/src/components/PdfViewer.tsx @@ -54,7 +54,7 @@ export function PDFViewer({pdfUrl, renderMode = 'canvas', header, footer, option return ( {header} - + {footer} ) diff --git a/packages/react-pdf/src/hooks/useInfiniteScroll.ts b/packages/react-pdf/src/hooks/useInfiniteScroll.ts new file mode 100644 index 0000000..d29e013 --- /dev/null +++ b/packages/react-pdf/src/hooks/useInfiniteScroll.ts @@ -0,0 +1,29 @@ +import {useEffect, useCallback, useMemo, useRef} from 'react' + +export default function useInfiniteScroll(onIntersect: () => void, options?: IntersectionObserverInit) { + const ref = useRef(null) + + const handleIntersect = useCallback( + ([entry]: IntersectionObserverEntry[]) => { + if (entry.isIntersecting) { + onIntersect() + } + }, + [onIntersect], + ) + + const observer = useMemo(() => { + return new IntersectionObserver(handleIntersect, options) + }, [handleIntersect, options]) + + useEffect(() => { + if (ref.current) { + observer.observe(ref.current) + } + return () => { + observer.disconnect() + } + }, [ref, observer]) + + return ref +}