Skip to content

Commit 8a5e9a5

Browse files
committed
feat: use item key as beforeMap key in diffArrayLepus
1 parent dc1e310 commit 8a5e9a5

File tree

2 files changed

+17
-2
lines changed

2 files changed

+17
-2
lines changed

packages/react/runtime/src/backgroundSnapshot.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,8 @@ export function hydrate(
470470
(a, b) => {
471471
helper(a, b);
472472
},
473+
// Should be `false` in hydrate as SerializedSnapshotInstance has no item-key
474+
false,
473475
);
474476
diffArrayAction(
475477
beforeChildNodes,

packages/react/runtime/src/hydrate.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@
55
import { componentAtIndexFactory, enqueueComponentFactory, gRecycleMap, gSignMap } from './list.js';
66
import { __pendingListUpdates } from './pendingListUpdates.js';
77
import { DynamicPartType } from './snapshot/dynamicPartType.js';
8+
import type { PlatformInfo } from './snapshot/platformInfo.js';
89
import { unref } from './snapshot/ref.js';
910
import type { SnapshotInstance } from './snapshot.js';
1011
import { isEmptyObject } from './utils.js';
1112

13+
const UNREACHABLE_ITEM_KEY_NOT_FOUND = 'UNREACHABLE_ITEM_KEY_NOT_FOUND';
14+
1215
export interface DiffResult<K> {
1316
$$diff: true;
1417
// insert No.j to new
@@ -21,6 +24,7 @@ export interface DiffResult<K> {
2124

2225
export interface Typed {
2326
type: string;
27+
__listItemPlatformInfo?: PlatformInfo;
2428
}
2529

2630
export function isEmptyDiffResult<K>(diffResult: DiffResult<K>): boolean {
@@ -34,6 +38,7 @@ export function diffArrayLepus<A extends Typed, B extends Typed>(
3438
after: B[],
3539
isSameType: (a: A, b: B) => boolean,
3640
onDiffChildren: (a: A, b: B, oldIndex: number, newIndex: number) => void,
41+
isListChildren: boolean,
3742
): DiffResult<B> {
3843
let lastPlacedIndex = 0;
3944
const result: DiffResult<B> = {
@@ -46,12 +51,18 @@ export function diffArrayLepus<A extends Typed, B extends Typed>(
4651

4752
for (let i = 0; i < before.length; i++) {
4853
const node = before[i]!;
49-
(beforeMap[node.type] ??= new Set()).add([node, i]);
54+
const key = isListChildren
55+
? node.__listItemPlatformInfo?.['item-key'] ?? UNREACHABLE_ITEM_KEY_NOT_FOUND
56+
: node.type;
57+
(beforeMap[key] ??= new Set()).add([node, i]);
5058
}
5159

5260
for (let i = 0; i < after.length; i++) {
5361
const afterNode = after[i]!;
54-
const beforeNodes = beforeMap[afterNode.type];
62+
const key = isListChildren
63+
? afterNode.__listItemPlatformInfo?.['item-key'] ?? UNREACHABLE_ITEM_KEY_NOT_FOUND
64+
: afterNode.type;
65+
const beforeNodes = beforeMap[key];
5566
let beforeNode: [A, number];
5667

5768
if (
@@ -258,6 +269,7 @@ export function hydrate(before: SnapshotInstance, after: SnapshotInstance, optio
258269
(a, b) => {
259270
hydrate(a, b, options);
260271
},
272+
false,
261273
);
262274
diffArrayAction(
263275
beforeChildNodes,
@@ -336,6 +348,7 @@ export function hydrate(before: SnapshotInstance, after: SnapshotInstance, optio
336348
}
337349
}
338350
},
351+
true,
339352
);
340353

341354
for (const i of diffResult.r) {

0 commit comments

Comments
 (0)