9
9
GHOST_ITEM_KEY ,
10
10
getItemRelativeTop ,
11
11
getCompareItemRelativeTop ,
12
- } from './util' ;
12
+ } from './utils/itemUtil' ;
13
+ import { getIndexByStartLoc , findListDiffIndex } from './utils/algorithmUtil' ;
13
14
14
15
type RenderFunc < T > = ( item : T ) => React . ReactNode ;
15
16
@@ -20,7 +21,7 @@ export interface ListProps<T> extends React.HTMLAttributes<any> {
20
21
dataSource : T [ ] ;
21
22
height ?: number ;
22
23
itemHeight ?: number ;
23
- itemKey ? : string ;
24
+ itemKey : string ;
24
25
component ?: string | React . FC < any > | React . ComponentClass < any > ;
25
26
}
26
27
@@ -112,7 +113,7 @@ class List<T> extends React.Component<ListProps<T>, ListState> {
112
113
113
114
// Record here since measure item height will get warning in `render`
114
115
for ( let index = startIndex ; index <= endIndex ; index += 1 ) {
115
- const eleKey = this . getItemKey ( index ) ;
116
+ const eleKey = this . getIndexKey ( index ) ;
116
117
this . itemElementHeights [ eleKey ] = getNodeHeight ( this . itemElements [ eleKey ] ) ;
117
118
}
118
119
@@ -124,12 +125,12 @@ class List<T> extends React.Component<ListProps<T>, ListState> {
124
125
scrollTop : this . listRef . current . scrollTop ,
125
126
scrollPtg : getElementScrollPercentage ( this . listRef . current ) ,
126
127
clientHeight : this . listRef . current . clientHeight ,
127
- getItemKey : this . getItemKey ,
128
+ getItemKey : this . getIndexKey ,
128
129
} ) ;
129
130
130
131
let startItemTop = locatedItemTop ;
131
132
for ( let index = itemIndex - 1 ; index >= startIndex ; index -= 1 ) {
132
- startItemTop -= this . itemElementHeights [ this . getItemKey ( index ) ] || 0 ;
133
+ startItemTop -= this . itemElementHeights [ this . getIndexKey ( index ) ] || 0 ;
133
134
}
134
135
135
136
this . setState ( { status : 'MEASURE_DONE' , startItemTop } ) ;
@@ -159,14 +160,15 @@ class List<T> extends React.Component<ListProps<T>, ListState> {
159
160
clientHeight : this . listRef . current . clientHeight ,
160
161
} ) ,
161
162
clientHeight : this . listRef . current . clientHeight ,
162
- getItemKey : ( index : number ) => this . getItemKey ( index , prevProps ) ,
163
+ getItemKey : ( index : number ) => this . getIndexKey ( index , prevProps ) ,
163
164
} ) ;
164
165
165
166
// 2. Find the compare item
166
- const removedItemIndex : number = prevProps . dataSource . findIndex ( ( _ , index ) => {
167
- const key = this . getItemKey ( index , prevProps ) ;
168
- return dataSource . every ( ( __ , nextIndex ) => key !== this . getItemKey ( nextIndex ) ) ;
169
- } ) ;
167
+ const removedItemIndex : number = findListDiffIndex (
168
+ prevProps . dataSource ,
169
+ dataSource ,
170
+ this . getItemKey ,
171
+ ) ;
170
172
let originCompareItemIndex = removedItemIndex - 1 ;
171
173
// Use next one since there are not more item before removed
172
174
if ( originCompareItemIndex < 0 ) {
@@ -180,7 +182,7 @@ class List<T> extends React.Component<ListProps<T>, ListState> {
180
182
compareItemIndex : originCompareItemIndex ,
181
183
startIndex : originStartIndex ,
182
184
endIndex : originEndIndex ,
183
- getItemKey : ( index : number ) => this . getItemKey ( index , prevProps ) ,
185
+ getItemKey : ( index : number ) => this . getIndexKey ( index , prevProps ) ,
184
186
itemElementHeights : this . itemElementHeights ,
185
187
} ) ;
186
188
@@ -195,7 +197,9 @@ class List<T> extends React.Component<ListProps<T>, ListState> {
195
197
const scrollHeight = dataSource . length * itemHeight ;
196
198
const { clientHeight } = this . listRef . current ;
197
199
const maxScrollTop = scrollHeight - clientHeight ;
198
- for ( let scrollTop = 0 ; scrollTop < maxScrollTop ; scrollTop += 1 ) {
200
+ for ( let i = 0 ; i < maxScrollTop ; i += 1 ) {
201
+ const scrollTop = getIndexByStartLoc ( 0 , maxScrollTop , originScrollTop , i ) ;
202
+
199
203
const scrollPtg = getScrollPercentage ( { scrollTop, scrollHeight, clientHeight } ) ;
200
204
const visibleCount = Math . ceil ( height / itemHeight ) ;
201
205
@@ -214,7 +218,7 @@ class List<T> extends React.Component<ListProps<T>, ListState> {
214
218
itemElementHeights : this . itemElementHeights ,
215
219
scrollPtg,
216
220
clientHeight,
217
- getItemKey : this . getItemKey ,
221
+ getItemKey : this . getIndexKey ,
218
222
} ) ;
219
223
220
224
const compareItemTop = getCompareItemRelativeTop ( {
@@ -223,7 +227,7 @@ class List<T> extends React.Component<ListProps<T>, ListState> {
223
227
compareItemIndex : originCompareItemIndex , // Same as origin index
224
228
startIndex,
225
229
endIndex,
226
- getItemKey : this . getItemKey ,
230
+ getItemKey : this . getIndexKey ,
227
231
itemElementHeights : this . itemElementHeights ,
228
232
} ) ;
229
233
@@ -295,8 +299,9 @@ class List<T> extends React.Component<ListProps<T>, ListState> {
295
299
} ) ;
296
300
} ;
297
301
298
- public getItemKey = ( index : number , props ?: ListProps < T > ) => {
299
- const { dataSource, itemKey } = props || this . props ;
302
+ public getIndexKey = ( index : number , props ?: ListProps < T > ) => {
303
+ const mergedProps = props || this . props ;
304
+ const { dataSource } = mergedProps ;
300
305
301
306
// Return ghost key as latest index item
302
307
if ( index === dataSource . length ) {
@@ -307,7 +312,13 @@ class List<T> extends React.Component<ListProps<T>, ListState> {
307
312
if ( ! item ) {
308
313
console . error ( 'Not find index item. Please report this since it is a bug.' ) ;
309
314
}
310
- return item && itemKey ? item [ itemKey ] : index ;
315
+
316
+ return this . getItemKey ( item , mergedProps ) ;
317
+ } ;
318
+
319
+ public getItemKey = ( item : T , props ?: ListProps < T > ) => {
320
+ const { itemKey } = props || this . props ;
321
+ return item ? item [ itemKey ] : null ;
311
322
} ;
312
323
313
324
/**
@@ -318,7 +329,7 @@ class List<T> extends React.Component<ListProps<T>, ListState> {
318
329
list . map ( ( item , index ) => {
319
330
const node = renderFunc ( item ) as React . ReactElement ;
320
331
const eleIndex = startIndex + index ;
321
- const eleKey = this . getItemKey ( eleIndex ) ;
332
+ const eleKey = this . getIndexKey ( eleIndex ) ;
322
333
323
334
// Pass `key` and `ref` for internal measure
324
335
return React . cloneElement ( node , {
0 commit comments