Skip to content

Commit 8d41c04

Browse files
test(mobile): attribute renders to state slots by their update queue
The counter skipped any slot holding a two-element array as a memo recompute, so a useState holding a pair was reported as a context render. Only useState, useReducer and store hooks have a queue. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 400dba5 commit 8d41c04

1 file changed

Lines changed: 5 additions & 6 deletions

File tree

‎apps/mobile/src/features/development/render-counter.ts‎

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ interface Fiber {
2020
}
2121
interface HookSlot {
2222
readonly memoizedState: unknown;
23+
/** Non-null only for useState and useReducer, the hooks that can schedule a render. */
24+
readonly queue: unknown;
2325
readonly next: HookSlot | null;
2426
}
2527
interface DevToolsHook {
@@ -71,12 +73,9 @@ function changedStateSlot(alternate: Fiber, node: Fiber): number {
7173
for (let index = 0; a && b && index < 800; index++) {
7274
const before = a.memoizedState;
7375
const after = b.memoizedState;
74-
if (!isEffect(after) && !Object.is(before, after)) {
75-
// A memo/callback slot whose deps did not change is a recompute, not a cause.
76-
const memoSlot =
77-
Array.isArray(before) && Array.isArray(after) && before.length === 2 && after.length === 2;
78-
if (!memoSlot) return index;
79-
}
76+
// Memo, callback and ref slots change because something upstream did; only a
77+
// state update is a cause of its own.
78+
if (b.queue !== null && !isEffect(after) && !Object.is(before, after)) return index;
8079
a = a.next;
8180
b = b.next;
8281
}

0 commit comments

Comments
 (0)