11import React , {
22 useState ,
33 useMemo ,
4- useEffect ,
5- useLayoutEffect ,
6- useRef ,
7- useCallback ,
8- ReactNode ,
9- createContext ,
10- } from 'react'
4+ useEffect , useRef , ReactNode
5+ } from 'react' ;
116
12- export function VirtualList (
13- props ,
7+ export type Props < ITEM > = {
8+ itemSize ?: number ,
9+ buffer ?: number ,
10+ items : ITEM [ ] ,
11+ renderItem : ( item : ITEM , index : number ) => ReactNode
12+ } & typeof defaultProps
13+
14+ export const defaultProps = {
15+ listSize : 1000 ,
16+ }
17+ export function VirtualList < ITEM > (
18+ props : Props < ITEM > & React . HTMLProps < HTMLElement > ,
1419) {
1520 const [ itemSize , setitemSize ] = useState ( props . itemSize || 100 ) ;
1621 const buffer = useMemo ( ( ) => props . buffer || Math . max ( itemSize * 5 , 100 ) , [ props . buffer , itemSize ] ) ;
1722 const count = props . items . length
18- const list = useRef ( null ) ;
19- const listInner = useRef ( null ) ;
23+ const list = useRef < HTMLDivElement > ( null ) ;
24+ const listInner = useRef < HTMLDivElement > ( null ) ;
2025 const prevScrollTop = useRef ( 0 ) ;
2126 const [ scrollTop , setscrollTop ] = useState ( 0 ) ;
22- const [ listSize , setlistSize ] = useState ( props . listSize || 1000 ) ;
27+ const [ listSize , setlistSize ] = useState ( props . listSize ) ;
28+
2329 //
2430 const totalSpace = itemSize * count
2531 let topSpace = scrollTop - buffer
2632 let bottomSpace = totalSpace - scrollTop - listSize - buffer
27- let startIndex , endIndex
33+ let startIndex = 0 , endIndex = 0
2834
2935 if ( topSpace <= 0 ) {
3036 topSpace = 0
@@ -41,7 +47,7 @@ export function VirtualList(
4147 bottomSpace = 0
4248 }
4349 const visible = props . items . slice ( startIndex , endIndex )
44- const listInnerStyle = { paddingTop : `${ topSpace } px` , boxSizing : 'border-box' }
50+ const listInnerStyle : any = { paddingTop : `${ topSpace } px` , boxSizing : 'border-box' }
4551 if ( bottomSpace < itemSize * 5 ) {
4652 listInnerStyle [ 'paddingBottom' ] = `${ bottomSpace } px`
4753 } else {
@@ -53,9 +59,9 @@ export function VirtualList(
5359 // get avg item size
5460 let count = 0
5561 let totalHeight = 0
56- for ( const el of listInner . current . children ) {
62+ for ( const el of listInner . current ! . children ) {
5763 const style = getComputedStyle ( el )
58- totalHeight += el . offsetHeight + parseFloat ( style . marginTop ) + parseFloat ( style . marginBottom )
64+ totalHeight += ( el as HTMLElement ) . offsetHeight + parseFloat ( style . marginTop ) + parseFloat ( style . marginBottom )
5965 count ++
6066 }
6167 setitemSize ( totalHeight / count )
@@ -76,4 +82,6 @@ export function VirtualList(
7682 { visible . map ( ( item , i ) => props . renderItem ( item , i + startIndex ) ) }
7783 </ div >
7884 </ div >
79- }
85+ }
86+
87+ VirtualList . defaultProps = defaultProps
0 commit comments