Skip to content

Commit 491563b

Browse files
committed
feat: use item key as beforeMap key in diffArrayLepus
1 parent 53eed0a commit 491563b

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
@@ -471,6 +471,8 @@ export function hydrate(
471471
(a, b) => {
472472
helper(a, b);
473473
},
474+
// Should be `false` in hydrate as SerializedSnapshotInstance has no item-key
475+
false,
474476
);
475477
diffArrayAction(
476478
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,
@@ -341,6 +353,7 @@ export function hydrate(before: SnapshotInstance, after: SnapshotInstance, optio
341353
}
342354
}
343355
},
356+
true,
344357
);
345358

346359
for (const i of diffResult.r) {

0 commit comments

Comments
 (0)