Skip to content

Commit b3dd9ca

Browse files
committed
refactor
1 parent fec58a2 commit b3dd9ca

File tree

2 files changed

+56
-22
lines changed

2 files changed

+56
-22
lines changed

src/List.tsx

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as React from 'react';
22
import Filler from './Filler';
3-
import { getLocationItem, getScrollPercentage, getNodeHeight } from './util';
3+
import { getScrollPercentage, getNodeHeight, getRangeIndex } from './util';
44

55
type RenderFunc<T> = (item: T) => React.ReactNode;
66

@@ -17,7 +17,6 @@ interface ListState {
1717
status: 'NONE' | 'MEASURE_START' | 'MEASURE_DONE';
1818

1919
scrollTop: number | null;
20-
scrollPtg: number;
2120
itemIndex: number;
2221
itemOffsetPtg: number;
2322
startIndex: number;
@@ -49,7 +48,6 @@ class List<T> extends React.Component<ListProps<T>, ListState> {
4948
state: ListState = {
5049
status: 'NONE',
5150
scrollTop: null,
52-
scrollPtg: 0,
5351
itemIndex: 0,
5452
itemOffsetPtg: 0,
5553
startIndex: 0,
@@ -76,8 +74,8 @@ class List<T> extends React.Component<ListProps<T>, ListState> {
7674
* Phase 5: Trigger re-render to use correct position
7775
*/
7876
public componentDidUpdate(prevProps: ListProps<T>) {
79-
const { status, scrollPtg, startIndex, endIndex, itemIndex, itemOffsetPtg } = this.state;
80-
const { dataSource, itemKey } = this.props;
77+
const { status, startIndex, endIndex, itemIndex, itemOffsetPtg } = this.state;
78+
const { dataSource } = this.props;
8179

8280
if (status === 'MEASURE_START') {
8381
// Record here since measure item height will get warning in `render`
@@ -87,6 +85,7 @@ class List<T> extends React.Component<ListProps<T>, ListState> {
8785
}
8886

8987
// Calculate top visible item top offset
88+
const scrollPtg = getScrollPercentage(this.listRef.current);
9089
const locatedItemHeight = this.itemElementHeights[this.getItemKey(itemIndex)] || 0;
9190
const locatedItemTop = scrollPtg * this.listRef.current.clientHeight;
9291
const locatedItemOffset = itemOffsetPtg * locatedItemHeight;
@@ -121,21 +120,21 @@ class List<T> extends React.Component<ListProps<T>, ListState> {
121120
}
122121

123122
const scrollPtg = getScrollPercentage(this.listRef.current);
124-
125-
const { index, offsetPtg } = getLocationItem(scrollPtg, dataSource.length);
126123
const visibleCount = Math.ceil(height / itemHeight);
127124

128-
const beforeCount = Math.ceil(scrollPtg * visibleCount);
129-
const afterCount = Math.ceil((1 - scrollPtg) * visibleCount);
125+
const { itemIndex, itemOffsetPtg, startIndex, endIndex } = getRangeIndex(
126+
scrollPtg,
127+
dataSource.length,
128+
visibleCount,
129+
);
130130

131131
this.setState({
132132
status: 'MEASURE_START',
133133
scrollTop,
134-
scrollPtg,
135-
itemIndex: index,
136-
itemOffsetPtg: offsetPtg,
137-
startIndex: Math.max(0, index - beforeCount),
138-
endIndex: Math.min(dataSource.length - 1, index + afterCount),
134+
itemIndex,
135+
itemOffsetPtg,
136+
startIndex,
137+
endIndex,
139138
});
140139
};
141140

src/util.ts

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ interface LocationItemResult {
1414
*
1515
* `total` should be the real count instead of `total - 1` in calculation.
1616
*/
17-
export function getLocationItem(scrollPtg: number, total: number): LocationItemResult {
17+
function getLocationItem(scrollPtg: number, total: number): LocationItemResult {
1818
const itemIndex = Math.floor(scrollPtg * total);
1919
const itemTopPtg = itemIndex / total;
2020
const itemBottomPtg = (itemIndex + 1) / total;
@@ -26,12 +26,15 @@ export function getLocationItem(scrollPtg: number, total: number): LocationItemR
2626
};
2727
}
2828

29-
export function getScrollPercentage(element: HTMLElement | null) {
30-
if (!element) {
31-
return 0;
32-
}
33-
34-
const { scrollTop, scrollHeight, clientHeight } = element;
29+
function internalGetScrollPercentage({
30+
scrollTop,
31+
scrollHeight,
32+
clientHeight,
33+
}: {
34+
scrollTop: number;
35+
scrollHeight: number;
36+
clientHeight: number;
37+
}): number {
3538
if (scrollHeight <= clientHeight) {
3639
return 0;
3740
}
@@ -40,6 +43,14 @@ export function getScrollPercentage(element: HTMLElement | null) {
4043
return scrollTopPtg;
4144
}
4245

46+
export function getScrollPercentage(element: HTMLElement | null) {
47+
if (!element) {
48+
return 0;
49+
}
50+
51+
return internalGetScrollPercentage(element);
52+
}
53+
4354
/**
4455
* Get node `offsetHeight`. We prefer node is a dom element directly.
4556
* But if not provided, downgrade to `findDOMNode` to get the real dom element.
@@ -52,4 +63,28 @@ export function getNodeHeight(node: HTMLElement) {
5263
return findDOMNode(node).offsetHeight;
5364
}
5465

55-
export function getStartItemTop(itemIndex: number) {}
66+
/**
67+
* Get display items start, end, located item index. This is pure math calculation
68+
*/
69+
export function getRangeIndex(scrollPtg: number, itemCount: number, visibleCount: number) {
70+
const { index, offsetPtg } = getLocationItem(scrollPtg, itemCount);
71+
72+
const beforeCount = Math.ceil(scrollPtg * visibleCount);
73+
const afterCount = Math.ceil((1 - scrollPtg) * visibleCount);
74+
75+
return {
76+
itemIndex: index,
77+
itemOffsetPtg: offsetPtg,
78+
startIndex: Math.max(0, index - beforeCount),
79+
endIndex: Math.min(itemCount - 1, index + afterCount),
80+
};
81+
}
82+
83+
interface ItemTopConfig {
84+
clientHeight: number;
85+
scrollTop: number;
86+
scrollPtg: number;
87+
itemOffsetPtg: number;
88+
}
89+
90+
export function getStartItemTop(itemIndex: number, itemElementHeights: { [key: string]: number }) {}

0 commit comments

Comments
 (0)