Skip to content

Commit 59d3fc4

Browse files
authored
only diff 1 item (#7)
1 parent 28719f8 commit 59d3fc4

File tree

3 files changed

+46
-29
lines changed

3 files changed

+46
-29
lines changed

src/List.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,12 @@ class List<T> extends React.Component<ListProps<T>, ListState<T>> {
184184
// Should trigger `onSkipRender` to tell that diff component is not render in the list
185185
if (data.length > prevData.length) {
186186
const { startIndex, endIndex } = this.state;
187-
if (onSkipRender && (changedItemIndex < startIndex || endIndex < changedItemIndex)) {
187+
if (
188+
onSkipRender &&
189+
(changedItemIndex === null ||
190+
changedItemIndex < startIndex ||
191+
endIndex < changedItemIndex)
192+
) {
188193
onSkipRender();
189194
}
190195
}
@@ -263,7 +268,7 @@ class List<T> extends React.Component<ListProps<T>, ListState<T>> {
263268
this.lockScroll = false;
264269
});
265270
});
266-
} else if (prevData.length !== data.length && height) {
271+
} else if (prevData.length !== data.length && changedItemIndex !== null && height) {
267272
/**
268273
* Re-calculate the item position since `data` length changed.
269274
* [IMPORTANT] We use relative position calculate here.

src/utils/algorithmUtil.ts

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -41,42 +41,44 @@ export function findListDiffIndex<T>(
4141
targetList: T[],
4242
getKey: (item: T) => string,
4343
): number | null {
44-
if (originList.length === targetList.length) {
44+
const originLen = originList.length;
45+
const targetLen = targetList.length;
46+
47+
// Skip if more than 1 content is diff
48+
if (Math.abs(originLen - targetLen) !== 1) {
4549
return null;
4650
}
4751

48-
let startIndex = 0;
49-
let endIndex = Math.max(originList.length, targetList.length) - 1;
50-
let midIndex = Math.floor((startIndex + endIndex) / 2);
52+
let shortList: T[];
53+
let longList: T[];
5154

52-
const keyCache: Map<T, string | { __EMPTY_ITEM__: true }> = new Map();
55+
if (originLen < targetLen) {
56+
shortList = originList;
57+
longList = targetList;
58+
} else {
59+
shortList = targetList;
60+
longList = originList;
61+
}
5362

54-
function getCacheKey(item: T) {
55-
if (!keyCache.has(item)) {
56-
keyCache.set(item, item !== undefined ? getKey(item) : { __EMPTY_ITEM__: true });
63+
const notExistKey = { __EMPTY_ITEM__: true };
64+
function getItemKey(item: T) {
65+
if (item) {
66+
return getKey(item);
5767
}
58-
return keyCache.get(item);
68+
return notExistKey;
5969
}
6070

61-
while (startIndex !== midIndex || midIndex !== endIndex) {
62-
const originMidKey = getCacheKey(originList[midIndex]);
63-
const targetMidKey = getCacheKey(targetList[midIndex]);
71+
// Loop to find diff one
72+
let diffIndex = 0;
73+
for (let i = 0; i < longList.length; i += 1) {
74+
const shortKey = getItemKey(shortList[i]);
75+
const longKey = getItemKey(longList[i]);
6476

65-
if (originMidKey === targetMidKey) {
66-
startIndex = midIndex;
67-
} else {
68-
endIndex = midIndex;
77+
if (shortKey !== longKey) {
78+
diffIndex = shortKey === getItemKey(longList[i + 1]) ? i : null;
79+
break;
6980
}
70-
71-
// Check if there only 2 index left
72-
if (startIndex === endIndex - 1) {
73-
return getCacheKey(originList[startIndex]) !== getCacheKey(targetList[startIndex])
74-
? startIndex
75-
: endIndex;
76-
}
77-
78-
midIndex = Math.floor((startIndex + endIndex) / 2);
7981
}
8082

81-
return midIndex;
83+
return diffIndex;
8284
}

tests/util.test.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,20 @@ describe('Util', () => {
8686
it('small list', () => {
8787
expect(findListDiffIndex([0], [], num => num)).toEqual(0);
8888
expect(findListDiffIndex([0, 1], [0], num => num)).toEqual(1);
89-
expect(findListDiffIndex([0, 1, 2], [0], num => num)).toEqual(1);
89+
expect(findListDiffIndex([0, 1, 2], [0], num => num)).toEqual(null);
9090
expect(findListDiffIndex([], [0], num => num)).toEqual(0);
9191
expect(findListDiffIndex([0], [0, 1], num => num)).toEqual(1);
9292
});
93+
94+
it('diff only 1', () => {
95+
expect(findListDiffIndex([0, 1, 2], [], num => num)).toEqual(null);
96+
expect(findListDiffIndex([0, 1, 2], [1, 2], num => num)).toEqual(0);
97+
expect(findListDiffIndex([0, 1, 2], [0, 2], num => num)).toEqual(1);
98+
expect(findListDiffIndex([0, 1, 2], [0, 1], num => num)).toEqual(2);
99+
expect(findListDiffIndex([0, 1, 2], [0], num => num)).toEqual(null);
100+
expect(findListDiffIndex([0, 1, 2], [1], num => num)).toEqual(null);
101+
expect(findListDiffIndex([0, 1, 2], [2], num => num)).toEqual(null);
102+
});
93103
});
94104
});
95105
});

0 commit comments

Comments
 (0)