@@ -68,6 +68,7 @@ export const VirtualList = forwardRef(function <ITEM>(
68
68
const listInner = useRef < HTMLDivElement > ( null ) ;
69
69
const prevScrollTop = useRef ( 0 ) ;
70
70
const scrollToIndexRef = useRef < { index : number , block : string } > ( ) ;
71
+ const [ shouldScrollToIndex , setshouldScrollToIndex ] = useState ( [ ] ) ;
71
72
const [ scrollTop , setscrollTop ] = useState ( 0 ) ;
72
73
const [ listSize , setlistSize ] = useState ( props . listSize ! ) ;
73
74
const [ forceRerender , setforceRerender ] = useState ( [ ] ) ; // change value to force rerender
@@ -92,6 +93,10 @@ export const VirtualList = forwardRef(function <ITEM>(
92
93
} else {
93
94
endIndex = count - Math . floor ( bottomSpace / itemSize )
94
95
}
96
+ if ( ! props . virtual ) {
97
+ startIndex = 0
98
+ endIndex = props . items . length
99
+ }
95
100
const mainVisibleIndices = Array . from ( { length : endIndex - startIndex } , ( _ , index ) => index + startIndex ) ;
96
101
let visibleIndices = mainVisibleIndices . concat ( props . persistentIndices || [ ] )
97
102
if ( props . persistentIndices ?. length ) {
@@ -128,18 +133,25 @@ export const VirtualList = forwardRef(function <ITEM>(
128
133
}
129
134
} , [ props . itemSize , props . items , forceRerender ] ) ;
130
135
//
136
+
131
137
const handleScroll = function ( event : unknown ) {
132
- if ( ignoreScrollOnce . current ) {
133
- ignoreScrollOnce . current = false
138
+ if ( ! props . virtual ) {
139
+ return
140
+ }
141
+ if ( scrollToIndexRef . current ) {
134
142
return
135
143
}
144
+
136
145
setlistSize ( list . current ! . clientHeight )
137
- const scrollTop2 = list . current ! . scrollTop
138
- if ( Math . abs ( prevScrollTop . current - scrollTop2 ) > ( props . triggerDistance ?? itemSize ) ) {
139
- setscrollTop ( scrollTop2 )
140
- prevScrollTop . current = scrollTop2
141
- } else if ( scrollToIndexRef . current ) {
142
- setforceRerender ( [ ] )
146
+
147
+ if ( ignoreScrollOnce . current ) {
148
+ ignoreScrollOnce . current = false
149
+ } else {
150
+ const scrollTop = list . current ! . scrollTop ;
151
+ if ( Math . abs ( prevScrollTop . current - scrollTop ) > ( props . triggerDistance ?? itemSize ) ) {
152
+ setscrollTop ( scrollTop )
153
+ prevScrollTop . current = scrollTop
154
+ }
143
155
}
144
156
// @ts -ignore
145
157
props . onScroll ?. call ( this , event )
@@ -151,12 +163,17 @@ export const VirtualList = forwardRef(function <ITEM>(
151
163
index,
152
164
block
153
165
}
154
- list . current ! . scrollTop = index * itemSize
166
+ const scrollTop = index * itemSize // estimated value
167
+ list . current ! . scrollTop = scrollTop
168
+ setscrollTop ( scrollTop )
169
+ prevScrollTop . current = scrollTop
170
+ setshouldScrollToIndex ( [ ] ) // ensure re-render but exclude itemSize. setforceRerender will re calculate avg itemSize, so don't use it here.
155
171
} ,
156
172
forceUpdate ( ) {
157
173
setforceRerender ( [ ] )
158
174
} ,
159
175
} ) , [ itemSize ] ) ;
176
+ // scrollToIndex
160
177
useLayoutEffect ( ( ) => {
161
178
if ( scrollToIndexRef . current ) {
162
179
const { index, block } = scrollToIndexRef . current ;
@@ -169,10 +186,10 @@ export const VirtualList = forwardRef(function <ITEM>(
169
186
ignoreScrollOnce . current = true
170
187
}
171
188
}
172
- } , [ visibleIndices ] )
189
+ } , [ shouldScrollToIndex ] )
173
190
//
174
191
return < div ref = { list } onScroll = { handleScroll } className = { props . className } style = { { overflow : 'auto' , ...props . style } } >
175
- < div ref = { listInner } style = { { display : 'flex' , flexDirection : 'column' , ...listInnerStyle } } >
192
+ < div ref = { listInner } style = { { display : 'flex' , flexDirection : 'column' , ...( props . virtual && listInnerStyle ) } } >
176
193
{ visible . map ( ( item , i ) => props . renderItem ( item , visibleIndices [ i ] ) ) }
177
194
</ div >
178
195
</ div >
0 commit comments