Skip to content

Commit d3aa289

Browse files
committed
refactor
1 parent c690260 commit d3aa289

File tree

1 file changed

+22
-19
lines changed

1 file changed

+22
-19
lines changed

src/List.tsx

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ interface ListState {
2222
itemOffsetPtg: number;
2323
startIndex: number;
2424
endIndex: number;
25+
/**
26+
* Calculated by `scrollTop`.
27+
* We cache in the state since if `dataSource` length change,
28+
* we need revert back to the located item index.
29+
*/
30+
startItemTop: number;
2531
}
2632

2733
/**
@@ -48,6 +54,7 @@ class List<T> extends React.Component<ListProps<T>, ListState> {
4854
itemOffsetPtg: 0,
4955
startIndex: 0,
5056
endIndex: 0,
57+
startItemTop: 0,
5158
};
5259

5360
listRef = React.createRef<HTMLElement>();
@@ -69,7 +76,7 @@ class List<T> extends React.Component<ListProps<T>, ListState> {
6976
* Phase 5: Trigger re-render to use correct position
7077
*/
7178
public componentDidUpdate(prevProps: ListProps<T>) {
72-
const { status, startIndex, endIndex } = this.state;
79+
const { status, scrollPtg, startIndex, endIndex, itemIndex, itemOffsetPtg } = this.state;
7380
const { dataSource, itemKey } = this.props;
7481

7582
if (status === 'MEASURE_START') {
@@ -80,7 +87,19 @@ class List<T> extends React.Component<ListProps<T>, ListState> {
8087
this.itemElementHeights[index] = getNodeHeight(this.itemElements[eleKey]);
8188
}
8289

83-
this.setState({ status: 'MEASURE_DONE' });
90+
// Calculate top visible item top offset
91+
const locatedItemHeight = this.getItemHeight(itemIndex);
92+
const locatedItemTop = scrollPtg * this.listRef.current.clientHeight;
93+
const locatedItemOffset = itemOffsetPtg * locatedItemHeight;
94+
const locatedItemMergedTop =
95+
this.listRef.current.scrollTop + locatedItemTop - locatedItemOffset;
96+
97+
let startItemTop = locatedItemMergedTop;
98+
for (let index = itemIndex - 1; index >= startIndex; index -= 1) {
99+
startItemTop -= this.getItemHeight(index);
100+
}
101+
102+
this.setState({ status: 'MEASURE_DONE', startItemTop });
84103
}
85104

86105
// Re-calculate the scroll position align with the current visible item position
@@ -165,25 +184,9 @@ class List<T> extends React.Component<ListProps<T>, ListState> {
165184
);
166185
}
167186

168-
const { status, startIndex, endIndex, itemIndex, itemOffsetPtg, scrollPtg } = this.state;
169-
187+
const { status, startIndex, endIndex, startItemTop } = this.state;
170188
const contentHeight = dataSource.length * itemHeight;
171189

172-
// TODO: refactor
173-
let startItemTop = 0;
174-
if (status === 'MEASURE_DONE') {
175-
const locatedItemHeight = this.getItemHeight(itemIndex);
176-
const locatedItemTop = scrollPtg * this.listRef.current.clientHeight;
177-
const locatedItemOffset = itemOffsetPtg * locatedItemHeight;
178-
const locatedItemMergedTop =
179-
this.listRef.current.scrollTop + locatedItemTop - locatedItemOffset;
180-
181-
startItemTop = locatedItemMergedTop;
182-
for (let index = itemIndex - 1; index >= startIndex; index -= 1) {
183-
startItemTop -= this.getItemHeight(index);
184-
}
185-
}
186-
187190
return (
188191
<Component
189192
style={{

0 commit comments

Comments
 (0)