From 56b14477e902ac076018be2e7bf2ea3092ac9e7d Mon Sep 17 00:00:00 2001 From: Ruslan Lesiutin Date: Thu, 21 Sep 2023 21:26:20 +0100 Subject: [PATCH] fix[devtools/useTransition]: don't check for dispatch property when determining if hook is stateful (#27365) https://github.com/facebook/react/pull/26740 introduced regression: React DevTools doesn't record updates for `useTransition` hook. I can add more details about things on DevTools side, if needed. The root cause is https://github.com/facebook/react/blob/491aec5d6113ce5bae7c10966bc38a4a8fc091a8/packages/react-reconciler/src/ReactFiberHooks.js#L2728-L2730 React DevTools expects dispatch to be present for stateful hooks that can schedule an update - https://github.com/facebook/react/blob/2eed1328478e8c923fcb4e6abf5efbd9e1233402/packages/react-devtools-shared/src/backend/renderer.js#L1422-L1428 With these changes, we still call dispatch in `startTransition`, but also patch `queue` object with it, so that React DevTools can recognise `useTransition` as stateful hook that can schedule update. I am not sure if this is the right approach to fix this, can we distinguish if `startTransition` was called from `useTransition` hook or as a standalone function? --- .../src/backend/renderer.js | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/packages/react-devtools-shared/src/backend/renderer.js b/packages/react-devtools-shared/src/backend/renderer.js index 506afcedcf36c..050793aa107b6 100644 --- a/packages/react-devtools-shared/src/backend/renderer.js +++ b/packages/react-devtools-shared/src/backend/renderer.js @@ -1419,22 +1419,20 @@ export function attach( const boundHasOwnProperty = hasOwnProperty.bind(queue); - // Detect the shape of useState() or useReducer() + // Detect the shape of useState() / useReducer() / useTransition() // using the attributes that are unique to these hooks // but also stable (e.g. not tied to current Lanes implementation) - const isStateOrReducer = - boundHasOwnProperty('pending') && - boundHasOwnProperty('dispatch') && - typeof queue.dispatch === 'function'; + // We don't check for dispatch property, because useTransition doesn't have it + if (boundHasOwnProperty('pending')) { + return true; + } // Detect useSyncExternalStore() - const isSyncExternalStore = + return ( boundHasOwnProperty('value') && boundHasOwnProperty('getSnapshot') && - typeof queue.getSnapshot === 'function'; - - // These are the only types of hooks that can schedule an update. - return isStateOrReducer || isSyncExternalStore; + typeof queue.getSnapshot === 'function' + ); } function didStatefulHookChange(prev: any, next: any): boolean {