Skip to content

Commit b8a557c

Browse files
Fix hooks render reason detection
1 parent 1882245 commit b8a557c

File tree

6 files changed

+75
-29
lines changed

6 files changed

+75
-29
lines changed

src/adapter/10/options.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -85,13 +85,6 @@ export function setupOptionsV10(
8585
prevHookName = options._addHookName || options.__a;
8686

8787
o._hook = o.__h = (c: Component, index: number, type: number) => {
88-
const vnode = (c as any)._vnode || (c as any).__v;
89-
const s = getStatefulHooks(vnode);
90-
if (s && Array.isArray(s) && s.length > 0 && getComponent(s[0])) {
91-
s[0]._oldValue = getStatefulHookValue(s);
92-
s[0]._index = index;
93-
}
94-
9588
if (type) {
9689
addHookStack(type);
9790
}
@@ -132,6 +125,19 @@ export function setupOptionsV10(
132125
if (typeof vnode.type === "function") {
133126
const name = getDisplayName(vnode, config);
134127
recordMark(`${name}_diff`);
128+
129+
const c = getComponent(vnode);
130+
const s = getStatefulHooks(vnode);
131+
if (s !== null && c !== null) {
132+
if (!(c as any)._oldHookValues) {
133+
(c as any)._oldHookValues = new Array(s.length).fill(undefined);
134+
}
135+
136+
for (let i = 0; i < s.length; i++) {
137+
const value = getStatefulHookValue(s[i]);
138+
(c as any)._oldHookValues[i] = value;
139+
}
140+
}
135141
}
136142

137143
if (vnode.type !== null) {

src/adapter/10/renderReason.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,12 @@ export function getRenderReasonPost<T extends SharedVNode>(
3030
// Check hooks
3131
const hooks = bindings.getStatefulHooks(next);
3232

33-
if (hooks !== null) {
33+
if (hooks !== null && Array.isArray(c._oldHookValues)) {
3434
const hooksChanged: string[] = [];
3535
for (let i = 0; i < hooks.length; i++) {
3636
if (
3737
bindings.isUseReducerOrState(hooks[i]) &&
38-
hooks[i]._oldValue !== bindings.getStatefulHookValue(hooks[i])
38+
c._oldHookValues[i] !== bindings.getStatefulHookValue(hooks[i])
3939
) {
4040
hooksChanged.push(String(i));
4141
}

src/adapter/protocol/events.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,8 @@ export function applyOperationsV2(store: Store, data: number[]) {
150150
rendered,
151151
commitRootId,
152152
);
153-
const map = store.profiler.renderReasons.value.set(commitRootId, reasons);
153+
const commitIdx = store.profiler.commits.peek().length - 1;
154+
const map = store.profiler.renderReasons.value.set(commitIdx, reasons);
154155
store.profiler.renderReasons.value = new Map(map);
155156
}
156157

src/view/components/profiler/components/RenderReasons.tsx

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -54,18 +54,17 @@ export function RenderReasons() {
5454
</dt>
5555
<dd class="render-reason-value">
5656
{hasReasons &&
57-
(reason.type === RenderReason.HOOKS_CHANGED
58-
? // <>
59-
// {reason!.items!.map(item => (
60-
// <span class="hook-number va-middle" key={item}>
61-
// {+item + 1}
62-
// </span>
63-
// ))}
64-
// </>
65-
//
66-
// TODO: Improve hooks detection
67-
null
68-
: reason!.items!.join(", "))}
57+
(reason.type === RenderReason.HOOKS_CHANGED ? (
58+
<>
59+
{reason!.items!.map(item => (
60+
<span class="hook-number va-middle" key={item}>
61+
{+item + 1}
62+
</span>
63+
))}
64+
</>
65+
) : (
66+
reason!.items!.join(", ")
67+
))}
6968
</dd>
7069
</dl>
7170
) : (

src/view/components/profiler/data/commits.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -136,12 +136,9 @@ export function createProfiler(): ProfilerState {
136136

137137
// Render reasons
138138
const activeReason = computed(() => {
139-
if (activeCommit.value !== null) {
140-
const commitId = activeCommit.value.commitRootId;
141-
const reason = renderReasons.value.get(commitId);
142-
if (reason) {
143-
return reason.get(selectedNodeId.value) || null;
144-
}
139+
const reason = renderReasons.value.get(activeCommitIdx.value);
140+
if (reason) {
141+
return reason.get(selectedNodeId.value) || null;
145142
}
146143

147144
return null;

test-e2e/tests/profiler/render-reasons.test.ts

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ test("Captures render reasons", async ({ page }) => {
5656
reasons = await devtools
5757
.locator('[data-testid="render-reasons"]')
5858
.textContent();
59-
expect(reasons).toEqual("Hooks changed:");
59+
expect(reasons).toEqual("Hooks changed:1");
6060

6161
// Force update
6262
await devtools.click('[data-testid="next-commit"]');
@@ -68,3 +68,46 @@ test("Captures render reasons", async ({ page }) => {
6868
.textContent();
6969
expect(reasons).toEqual("Force update");
7070
});
71+
72+
test("Captures hook render reasons", async ({ page }) => {
73+
const { devtools } = await gotoTest(page, "hooks-multiple");
74+
75+
await devtools.locator(locateTab("SETTINGS")).click();
76+
await devtools.click('[data-testid="toggle-render-reason"]');
77+
78+
// Start profiling
79+
await devtools.locator(locateTab("PROFILER")).click();
80+
await clickRecordButton(devtools);
81+
await page.click('button:has-text("S1++")');
82+
await page.click('button:has-text("S2++")');
83+
await page.click('button:has-text("S3++")');
84+
await page.click('button:has-text("S1++")');
85+
86+
await wait(1000);
87+
await clickRecordButton(devtools);
88+
89+
await devtools.locator(locateFlame("App")).click();
90+
91+
let reasons = await devtools
92+
.locator('[data-testid="render-reasons"]')
93+
.textContent();
94+
expect(reasons).toEqual("Hooks changed:1");
95+
96+
await devtools.click('[data-testid="next-commit"]');
97+
reasons = await devtools
98+
.locator('[data-testid="render-reasons"]')
99+
.textContent();
100+
expect(reasons).toEqual("Hooks changed:2");
101+
102+
await devtools.click('[data-testid="next-commit"]');
103+
reasons = await devtools
104+
.locator('[data-testid="render-reasons"]')
105+
.textContent();
106+
expect(reasons).toEqual("Hooks changed:3");
107+
108+
await devtools.click('[data-testid="next-commit"]');
109+
reasons = await devtools
110+
.locator('[data-testid="render-reasons"]')
111+
.textContent();
112+
expect(reasons).toEqual("Hooks changed:1");
113+
});

0 commit comments

Comments
 (0)