Skip to content

Commit

Permalink
[#15] react pdf 무한 스크롤을 구현합니다.
Browse files Browse the repository at this point in the history
  • Loading branch information
2-one-week committed Apr 24, 2024
1 parent 32f2670 commit ed9899f
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 6 deletions.
27 changes: 22 additions & 5 deletions packages/react-pdf/src/components/Pages.tsx
Original file line number Diff line number Diff line change
@@ -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'
Expand All @@ -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}) {
Expand Down Expand Up @@ -38,15 +40,30 @@ export const Page = memo(function Page({renderMode, pageNumber}: PagesProps & {p
)
})

export const Pages = memo(function Pages({renderMode, children}: PropsWithChildren<PagesProps>) {
export const Pages = memo(function Pages({renderMode, lazyLoading, children}: PropsWithChildren<PagesProps>) {
const {pdf} = usePdfContext()
const pageNumbers = Array.from({length: pdf.numPages}, (_, index) => index + 1)
const [renderPages, setRenderPages] = useState<number[]>(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 <Page key={index} renderMode={renderMode} pageNumber={index + 1} />
{(lazyLoading ? renderPages : pageNumbers).map((pageNum) => {
return (
<div key={pageNum} ref={lazyLoading && renderPages.length === pageNum ? ref : null}>
<Page renderMode={renderMode} pageNumber={pageNum} />
</div>
)
})}
{children}
</>
Expand Down
2 changes: 1 addition & 1 deletion packages/react-pdf/src/components/PdfViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export function PDFViewer({pdfUrl, renderMode = 'canvas', header, footer, option
return (
<PDFProvider pdf={pdf} options={options}>
{header}
<Pages renderMode={renderMode} />
<Pages renderMode={renderMode} lazyLoading={options?.lazyLoading || true} />
{footer}
</PDFProvider>
)
Expand Down
29 changes: 29 additions & 0 deletions packages/react-pdf/src/hooks/useInfiniteScroll.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import {useEffect, useCallback, useMemo, useRef} from 'react'

export default function useInfiniteScroll(onIntersect: () => void, options?: IntersectionObserverInit) {
const ref = useRef<HTMLDivElement | null>(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
}

0 comments on commit ed9899f

Please sign in to comment.