From 7e8e9f23887f28a262ec3c48f47c3651a89d4a8e Mon Sep 17 00:00:00 2001 From: Biki das Date: Sat, 11 Oct 2025 23:47:04 +0530 Subject: [PATCH] Fix DevTools hook indexing for useSyncExternalStore useSyncExternalStore creates two internal hooks namely mountEffect & pushSimpleEffect, but should be reported as a single hook in DevTools. Skip internal hooks when calculating indices so the profiler shows the correct hook that triggered the render --- .../src/backend/fiber/renderer.js | 28 ++++++++++++++----- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/packages/react-devtools-shared/src/backend/fiber/renderer.js b/packages/react-devtools-shared/src/backend/fiber/renderer.js index ba214db05c7..df13c0fe3f8 100644 --- a/packages/react-devtools-shared/src/backend/fiber/renderer.js +++ b/packages/react-devtools-shared/src/backend/fiber/renderer.js @@ -1913,6 +1913,19 @@ export function attach( return false; } + function isUseSyncExternalStoreHook(hookObject: any): boolean { + const queue = hookObject.queue; + if (!queue) { + return false; + } + const boundHasOwnProperty = hasOwnProperty.bind(queue); + return ( + typeof queue.getSnapshot === 'function' && + boundHasOwnProperty('value') && + boundHasOwnProperty('getSnapshot') + ); + } + function isHookThatCanScheduleUpdate(hookObject: any) { const queue = hookObject.queue; if (!queue) { @@ -1929,12 +1942,7 @@ export function attach( return true; } - // Detect useSyncExternalStore() - return ( - boundHasOwnProperty('value') && - boundHasOwnProperty('getSnapshot') && - typeof queue.getSnapshot === 'function' - ); + return isUseSyncExternalStoreHook(hookObject); } function didStatefulHookChange(prev: any, next: any): boolean { @@ -1959,9 +1967,15 @@ export function attach( if (didStatefulHookChange(prev, next)) { indices.push(index); } + if (isUseSyncExternalStoreHook(next)) { + if (next.next !== null) { + next = next.next; + prev = prev.next; + } + } + index++; next = next.next; prev = prev.next; - index++; } return indices;