@@ -9,7 +9,7 @@ const defaultKeyExtractor = index => index
99export function useVirtual ( {
1010 size = 0 ,
1111 estimateSize = defaultEstimateSize ,
12- overscan = 0 ,
12+ overscan = 1 ,
1313 paddingStart = 0 ,
1414 paddingEnd = 0 ,
1515 parentRef,
@@ -82,6 +82,9 @@ export function useVirtual({
8282
8383 useIsomorphicLayoutEffect ( ( ) => {
8484 if ( ! element ) {
85+ setRange ( { start : 0 , end : 0 } )
86+ latestRef . current . scrollOffset = undefined
87+
8588 return
8689 }
8790
@@ -239,26 +242,43 @@ export function useVirtual({
239242 }
240243}
241244
245+ const findNearestBinarySearch = ( low , high , getCurrentValue , value ) => {
246+ while ( low <= high ) {
247+ let middle = ( ( low + high ) / 2 ) | 0
248+ let currentValue = getCurrentValue ( middle )
249+
250+ if ( currentValue < value ) {
251+ low = middle + 1
252+ } else if ( currentValue > value ) {
253+ high = middle - 1
254+ } else {
255+ return middle
256+ }
257+ }
258+
259+ if ( low > 0 ) {
260+ return low - 1
261+ } else {
262+ return 0
263+ }
264+ }
265+
242266function calculateRange (
243267 { overscan, measurements, outerSize, scrollOffset } ,
244268 prevRange
245269) {
246- const total = measurements . length
247- let start = total - 1
248- while ( start > 0 && measurements [ start ] . end >= scrollOffset ) {
249- start -= 1
250- }
251- let end = 0
252- while (
253- end < total - 1 &&
254- measurements [ end ] . start <= scrollOffset + outerSize
255- ) {
256- end += 1
270+ const size = measurements . length - 1
271+ const getOffset = index => measurements [ index ] . start
272+
273+ let start = findNearestBinarySearch ( 0 , size , getOffset , scrollOffset )
274+ let end = start
275+
276+ while ( end < size && measurements [ end ] . end < scrollOffset + outerSize ) {
277+ end ++
257278 }
258279
259- // Always add at least one overscan item, so focus will work
260280 start = Math . max ( start - overscan , 0 )
261- end = Math . min ( end + overscan , total - 1 )
281+ end = Math . min ( end + overscan , size )
262282
263283 if ( ! prevRange || prevRange . start !== start || prevRange . end !== end ) {
264284 return { start, end }
0 commit comments